diff --git a/src/Qubic.vcxproj b/src/Qubic.vcxproj index f4cfb3115..db159d520 100644 --- a/src/Qubic.vcxproj +++ b/src/Qubic.vcxproj @@ -46,7 +46,6 @@ - diff --git a/src/Qubic.vcxproj.filters b/src/Qubic.vcxproj.filters index e80136b24..7925cb33b 100644 --- a/src/Qubic.vcxproj.filters +++ b/src/Qubic.vcxproj.filters @@ -336,9 +336,6 @@ contracts - - contracts - diff --git a/src/contract_core/contract_def.h b/src/contract_core/contract_def.h index 91bc2267f..29988c27a 100644 --- a/src/contract_core/contract_def.h +++ b/src/contract_core/contract_def.h @@ -79,11 +79,7 @@ #define CONTRACT_INDEX SWATCH_CONTRACT_INDEX #define CONTRACT_STATE_TYPE SWATCH #define CONTRACT_STATE2_TYPE SWATCH2 -#ifdef OLD_SWATCH -#include "contracts/SupplyWatcher_old.h" -#else #include "contracts/SupplyWatcher.h" -#endif #undef CONTRACT_INDEX #undef CONTRACT_STATE_TYPE @@ -215,54 +211,36 @@ #define CONTRACT_STATE2_TYPE QRWA2 #include "contracts/qRWA.h" -#ifndef NO_QRP - -constexpr unsigned short qrpContractIndex = CONTRACT_INDEX + 1; - #undef CONTRACT_INDEX #undef CONTRACT_STATE_TYPE #undef CONTRACT_STATE2_TYPE -#define QRP_CONTRACT_INDEX qrpContractIndex +#define QRP_CONTRACT_INDEX 21 #define CONTRACT_INDEX QRP_CONTRACT_INDEX #define CONTRACT_STATE_TYPE QRP #define CONTRACT_STATE2_TYPE QRP2 #include "contracts/QReservePool.h" -#endif // NO_QRP - -#ifndef NO_QTF - -constexpr unsigned short qtfContractIndex = CONTRACT_INDEX + 1; - #undef CONTRACT_INDEX #undef CONTRACT_STATE_TYPE #undef CONTRACT_STATE2_TYPE -#define QTF_CONTRACT_INDEX qtfContractIndex +#define QTF_CONTRACT_INDEX 22 #define CONTRACT_INDEX QTF_CONTRACT_INDEX #define CONTRACT_STATE_TYPE QTF #define CONTRACT_STATE2_TYPE QTF2 #include "contracts/QThirtyFour.h" -#endif // NO_QTF - -#ifndef NO_QDUEL - -constexpr unsigned short qduelContractIndex = CONTRACT_INDEX + 1; - #undef CONTRACT_INDEX #undef CONTRACT_STATE_TYPE #undef CONTRACT_STATE2_TYPE -#define QDUEL_CONTRACT_INDEX qduelContractIndex +#define QDUEL_CONTRACT_INDEX 23 #define CONTRACT_INDEX QDUEL_CONTRACT_INDEX #define CONTRACT_STATE_TYPE QDUEL #define CONTRACT_STATE2_TYPE QDUEL2 #include "contracts/QDuel.h" -#endif // NO_QDUEL - // new contracts should be added above this line #ifdef INCLUDE_CONTRACT_TEST_EXAMPLES @@ -371,15 +349,9 @@ constexpr struct ContractDescription {"QIP", 189, 10000, sizeof(QIP)}, // proposal in epoch 187, IPO in 188, construction and first use in 189 {"QRAFFLE", 192, 10000, sizeof(QRAFFLE)}, // proposal in epoch 190, IPO in 191, construction and first use in 192 {"QRWA", 197, 10000, sizeof(QRWA)}, // proposal in epoch 195, IPO in 196, construction and first use in 197 -#ifndef NO_QRP {"QRP", 199, 10000, sizeof(IPO)}, // proposal in epoch 197, IPO in 198, construction and first use in 199 -#endif -#ifndef NO_QTF {"QTF", 199, 10000, sizeof(QTF)}, // proposal in epoch 197, IPO in 198, construction and first use in 199 -#endif -#ifndef NO_QDUEL {"QDUEL", 199, 10000, sizeof(QDUEL)}, // proposal in epoch 197, IPO in 198, construction and first use in 199 -#endif // new contracts should be added above this line #ifdef INCLUDE_CONTRACT_TEST_EXAMPLES {"TESTEXA", 138, 10000, sizeof(TESTEXA)}, @@ -496,15 +468,9 @@ static void initializeContracts() REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QIP); REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QRAFFLE); REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QRWA); -#ifndef NO_QRP REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QRP); -#endif -#ifndef NO_QTF REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QTF); -#endif -#ifndef NO_QDUEL REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QDUEL); -#endif // new contracts should be added above this line #ifdef INCLUDE_CONTRACT_TEST_EXAMPLES REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(TESTEXA); diff --git a/src/contracts/QIP.h b/src/contracts/QIP.h index c0ec8a12a..55ea8eab3 100644 --- a/src/contracts/QIP.h +++ b/src/contracts/QIP.h @@ -288,6 +288,10 @@ struct QIP : public ContractBase { if (input.indexOfICO >= state.numberOfICO) { + if (qpi.invocationReward() > 0) + { + qpi.transfer(qpi.invocator(), qpi.invocationReward()); + } locals.log._contractIndex = SELF_INDEX; locals.log._type = QIPLogInfo::QIP_ICONotFound; locals.log.dst = qpi.invocator(); @@ -306,6 +310,10 @@ struct QIP : public ContractBase } else { + if (qpi.invocationReward() > 0) + { + qpi.transfer(qpi.invocator(), qpi.invocationReward()); + } locals.log._contractIndex = SELF_INDEX; locals.log._type = QIPLogInfo::QIP_invalidAmount; locals.log.dst = qpi.invocator(); @@ -324,6 +332,10 @@ struct QIP : public ContractBase } else { + if (qpi.invocationReward() > 0) + { + qpi.transfer(qpi.invocator(), qpi.invocationReward()); + } locals.log._contractIndex = SELF_INDEX; locals.log._type = QIPLogInfo::QIP_invalidAmount; locals.log.dst = qpi.invocator(); @@ -342,6 +354,10 @@ struct QIP : public ContractBase } else { + if (qpi.invocationReward() > 0) + { + qpi.transfer(qpi.invocator(), qpi.invocationReward()); + } locals.log._contractIndex = SELF_INDEX; locals.log._type = QIPLogInfo::QIP_invalidAmount; locals.log.dst = qpi.invocator(); @@ -353,6 +369,10 @@ struct QIP : public ContractBase } else { + if (qpi.invocationReward() > 0) + { + qpi.transfer(qpi.invocator(), qpi.invocationReward()); + } locals.log._contractIndex = SELF_INDEX; locals.log._type = QIPLogInfo::QIP_invalidEpoch; locals.log.dst = qpi.invocator(); @@ -363,6 +383,10 @@ struct QIP : public ContractBase } if (input.amount * locals.price > (uint64)qpi.invocationReward()) { + if (qpi.invocationReward() > 0) + { + qpi.transfer(qpi.invocator(), qpi.invocationReward()); + } locals.log._contractIndex = SELF_INDEX; locals.log._type = QIPLogInfo::QIP_insufficientInvocationReward; locals.log.dst = qpi.invocator(); @@ -479,6 +503,24 @@ struct QIP : public ContractBase state.transferRightsFee = 100; } + struct BEGIN_EPOCH_locals + { + id address1; + id address2; + }; + + BEGIN_EPOCH_WITH_LOCALS() + { + locals.address1 = ID(_K, _D, _F, _D, _H, _J, _F, _E, _B, _J, _W, _E, _Z, _D, _F, _I, _C, _T, _P, _Z, _N, _N, _D, _T, _A, _Z, _S, _A, _H, _F, _G, _Q, _H, _D, _O, _C, _X, _R, _P, _G, _D, _D, _I, _B, _F, _P, _D, _D, _Q, _Z, _H, _O, _V, _H, _V, _D); + locals.address2 = ID(_Z, _V, _V, _C, _R, _T, _G, _Y, _W, _B, _K, _H, _X, _D, _F, _M, _Q, _D, _X, _F, _V, _B, _D, _N, _N, _L, _I, _D, _K, _Q, _F, _N, _B, _Q, _K, _V, _U, _L, _R, _N, _H, _F, _E, _Z, _K, _C, _K, _B, _H, _X, _I, _B, _E, _N, _S, _E); + + if (qpi.epoch() == 199) + { + qpi.transfer(locals.address1, 30000000); + qpi.transfer(locals.address2, 100000000); + } + } + struct END_EPOCH_locals { ICOInfo ico; diff --git a/src/contracts/QThirtyFour.h b/src/contracts/QThirtyFour.h index 77d179978..6093728ea 100644 --- a/src/contracts/QThirtyFour.h +++ b/src/contracts/QThirtyFour.h @@ -61,11 +61,7 @@ constexpr uint8 QTF_DEFAULT_SCHEDULE = 1 << SATURDAY | 1u << WEDNESDAY; constexpr uint8 QTF_DEFAULT_DRAW_HOUR = 11; // 11:00 UTC constexpr uint32 QTF_DEFAULT_INIT_TIME = 22u << 9 | 4u << 5 | 13u; // RL_DEFAULT_INIT_TIME -const id QTF_ADDRESS_DEV_TEAM = ID(_Z, _T, _Z, _E, _A, _Q, _G, _U, _P, _I, _K, _T, _X, _F, _Y, _X, _Y, _E, _I, _T, _L, _A, _K, _F, _T, _D, _X, _C, _R, - _L, _W, _E, _T, _H, _N, _G, _H, _D, _Y, _U, _W, _E, _Y, _Q, _N, _Q, _S, _R, _H, _O, _W, _M, _U, _J, _L, _E); -const id QTF_RANDOM_LOTTERY_CONTRACT_ID = id(RL_CONTRACT_INDEX, 0, 0, 0); constexpr uint64 QTF_RANDOM_LOTTERY_ASSET_NAME = 19538; // RL -const id QTF_RESERVE_POOL_CONTRACT_ID = id(QRP_CONTRACT_INDEX, 0, 0, 0); struct QTF2 { @@ -691,7 +687,8 @@ struct QTF : ContractBase // Contract lifecycle methods INITIALIZE() { - state.teamAddress = QTF_ADDRESS_DEV_TEAM; + state.teamAddress = ID(_Z, _T, _Z, _E, _A, _Q, _G, _U, _P, _I, _K, _T, _X, _F, _Y, _X, _Y, _E, _I, _T, _L, _A, _K, _F, _T, _D, _X, _C, _R, + _L, _W, _E, _T, _H, _N, _G, _H, _D, _Y, _U, _W, _E, _Y, _Q, _N, _Q, _S, _R, _H, _O, _W, _M, _U, _J, _L, _E); state.ownerAddress = state.teamAddress; state.ticketPrice = QTF_TICKET_PRICE; state.targetJackpot = QTF_DEFAULT_TARGET_JACKPOT; @@ -1501,7 +1498,7 @@ struct QTF : ContractBase // Transfer reserve overflow to QReservePool if (locals.reserveAdd > 0) { - qpi.transfer(QTF_RESERVE_POOL_CONTRACT_ID, locals.reserveAdd); + qpi.transfer(id(QRP_CONTRACT_INDEX, 0, 0, 0), locals.reserveAdd); } if (locals.devPayout > 0) @@ -1534,7 +1531,7 @@ struct QTF : ContractBase locals.rlPayback = locals.distPayout - smul(locals.dividendPerShare, locals.rlTotalShares); if (locals.rlPayback > 0) { - qpi.transfer(QTF_RANDOM_LOTTERY_CONTRACT_ID, locals.rlPayback); + qpi.transfer(id(RL_CONTRACT_INDEX, 0, 0, 0), locals.rlPayback); } } } diff --git a/src/contracts/QUtil.h b/src/contracts/QUtil.h index fe39068a5..b9fe77969 100644 --- a/src/contracts/QUtil.h +++ b/src/contracts/QUtil.h @@ -81,6 +81,7 @@ struct QUTILSendToManyBenchmarkLog uint32 logType; id startId; sint64 dstCount; + sint64 numTransfersEach; sint8 _terminator; // Only data before "_terminator" are logged }; @@ -848,6 +849,7 @@ struct QUTIL : public ContractBase locals.logBenchmark.startId = qpi.invocator(); locals.logBenchmark.logType = QUTIL_STMB_LOG_TYPE; locals.logBenchmark.dstCount = input.dstCount; + locals.logBenchmark.numTransfersEach = input.numTransfersEach; LOG_INFO(locals.logBenchmark); LOG_PAUSE(); diff --git a/src/contracts/Qswap.h b/src/contracts/Qswap.h index b73333e49..145d7cdb4 100644 --- a/src/contracts/Qswap.h +++ b/src/contracts/Qswap.h @@ -340,6 +340,9 @@ struct QSWAP : public ContractBase uint64 burnEarnedFee; // Total burn fees collected (to be burned in END_TICK) uint64 burnedAmount; // Total amount actually burned + uint32 cachedIssuanceFee; + uint32 cachedTransferFee; + // ----------------------------- // ---- state variables end ---- // ----------------------------- @@ -360,15 +363,26 @@ struct QSWAP : public ContractBase prod = uint128(a) * uint128(b); - // (prod + 1) / 2; - z = div(prod+uint128(1), uint128(2)); - y = prod; + y = uint128(0); + + z = uint128(1) << uint128(0, 126); + while (z > prod) + { + z >>= uint128(0, 2); + } - while(z < y) + while (z) { - y = z; - // (prod / z + z) / 2; - z = div((div(prod, z) + z), uint128(2)); + if (prod >= y + z) + { + prod -= y + z; + y = (y >> uint128(0, 1)) + z; + } + else + { + y >>= uint128(0, 1); + } + z >>= uint128(0, 2); } return sint64(y.low); @@ -502,20 +516,11 @@ struct QSWAP : public ContractBase } } - struct Fees_locals - { - QX::Fees_input feesInput; - QX::Fees_output feesOutput; - }; - - PUBLIC_FUNCTION_WITH_LOCALS(Fees) + PUBLIC_FUNCTION(Fees) { - - CALL_OTHER_CONTRACT_FUNCTION(QX, Fees, locals.feesInput, locals.feesOutput); - - output.assetIssuanceFee = locals.feesOutput.assetIssuanceFee; - output.poolCreationFee = uint32(div(uint64(locals.feesOutput.assetIssuanceFee) * uint64(state.poolCreationFeeRate), uint64(QSWAP_FEE_BASE_100))); - output.transferFee = locals.feesOutput.transferFee; + output.assetIssuanceFee = state.cachedIssuanceFee; + output.poolCreationFee = uint32(div(uint64(state.cachedIssuanceFee) * uint64(state.poolCreationFeeRate), uint64(QSWAP_FEE_BASE_100))); + output.transferFee = state.cachedTransferFee; output.swapFee = state.swapFeeRate; output.shareholderFee = state.shareholderFeeRate; output.investRewardsFee = state.investRewardsFeeRate; @@ -629,7 +634,7 @@ struct QSWAP : public ContractBase } } - // no available solt for new pool + // no available slot for new pool if (locals.poolSlot == -1) { return; @@ -687,7 +692,7 @@ struct QSWAP : public ContractBase } } - // no available solt for new pool + // no available slot for new pool if (locals.poolSlot == -1) { return; @@ -750,7 +755,7 @@ struct QSWAP : public ContractBase } } - // no available solt for new pool + // no available slot for new pool if (locals.poolSlot == -1) { return; @@ -819,7 +824,7 @@ struct QSWAP : public ContractBase } } - // no available solt for new pool + // no available slot for new pool if (locals.poolSlot == -1) { return; @@ -857,19 +862,11 @@ struct QSWAP : public ContractBase // // procedure -// - struct IssueAsset_locals - { - QX::Fees_input feesInput; - QX::Fees_output feesOutput; - }; - - PUBLIC_PROCEDURE_WITH_LOCALS(IssueAsset) +// + PUBLIC_PROCEDURE(IssueAsset) { - CALL_OTHER_CONTRACT_FUNCTION(QX, Fees, locals.feesInput, locals.feesOutput); - output.issuedNumberOfShares = 0; - if ((qpi.invocationReward() < locals.feesOutput.assetIssuanceFee)) + if ((qpi.invocationReward() < state.cachedIssuanceFee)) { if (qpi.invocationReward() > 0) { @@ -913,11 +910,11 @@ struct QSWAP : public ContractBase } else { - if (qpi.invocationReward() > locals.feesOutput.assetIssuanceFee) + if (qpi.invocationReward() > state.cachedIssuanceFee) { - qpi.transfer(qpi.invocator(), qpi.invocationReward() - locals.feesOutput.assetIssuanceFee); + qpi.transfer(qpi.invocator(), qpi.invocationReward() - state.cachedIssuanceFee); } - state.shareholderEarnedFee += locals.feesOutput.assetIssuanceFee; + state.shareholderEarnedFee += state.cachedIssuanceFee; } } @@ -926,8 +923,6 @@ struct QSWAP : public ContractBase id poolID; sint64 poolSlot; PoolBasicState poolBasicState; - QX::Fees_input feesInput; - QX::Fees_output feesOutput; uint32 poolCreationFee; uint32 i0, i1; @@ -939,8 +934,7 @@ struct QSWAP : public ContractBase { output.success = false; - CALL_OTHER_CONTRACT_FUNCTION(QX, Fees, locals.feesInput, locals.feesOutput); - locals.poolCreationFee = uint32(div(uint64(locals.feesOutput.assetIssuanceFee) * uint64(state.poolCreationFeeRate), uint64(QSWAP_FEE_BASE_100))); + locals.poolCreationFee = uint32(div(uint64(state.cachedIssuanceFee) * uint64(state.poolCreationFeeRate), uint64(QSWAP_FEE_BASE_100))); // fee check if(qpi.invocationReward() < locals.poolCreationFee ) @@ -983,7 +977,7 @@ struct QSWAP : public ContractBase } } - // no available solt for new pool + // no available slot for new pool if (locals.poolSlot == -1) { qpi.transfer(qpi.invocator(), qpi.invocationReward()); @@ -1498,6 +1492,8 @@ struct QSWAP : public ContractBase uint128 feeToQx; uint128 feeToBurn; + + sint64 totalFee; }; // given an input qu amountIn, only execute swap in case (amountOut >= amountOutMin) @@ -1581,9 +1577,12 @@ struct QSWAP : public ContractBase locals.feeToInvestRewards = div(locals.swapFee * uint128(state.investRewardsFeeRate), uint128(QSWAP_FEE_BASE_100)); locals.feeToBurn = div(locals.swapFee * uint128(state.burnFeeRate), uint128(QSWAP_FEE_BASE_100)); + locals.totalFee = sint64(locals.feeToShareholders.low) + sint64(locals.feeToQx.low) + sint64(locals.feeToInvestRewards.low) + sint64(locals.feeToBurn.low); + // Overflow protection: ensure all fees fit in uint64 - if (locals.feeToShareholders.high != 0 || locals.feeToQx.high != 0 || - locals.feeToInvestRewards.high != 0 || locals.feeToBurn.high != 0) + if (locals.feeToShareholders.high != 0 || locals.feeToQx.high != 0 + || locals.feeToInvestRewards.high != 0 || locals.feeToBurn.high != 0 + || locals.quAmountIn < locals.totalFee) { qpi.transfer(qpi.invocator(), qpi.invocationReward()); return; @@ -1612,7 +1611,7 @@ struct QSWAP : public ContractBase state.investRewardsEarnedFee += locals.feeToInvestRewards.low; state.burnEarnedFee += locals.feeToBurn.low; - locals.poolBasicState.reservedQuAmount += locals.quAmountIn - sint64(locals.feeToShareholders.low) - sint64(locals.feeToQx.low) - sint64(locals.feeToInvestRewards.low) - sint64(locals.feeToBurn.low); + locals.poolBasicState.reservedQuAmount += locals.quAmountIn - locals.totalFee; locals.poolBasicState.reservedAssetAmount -= locals.assetAmountOut; state.mPoolBasicStates.set(locals.poolSlot, locals.poolBasicState); @@ -1642,6 +1641,8 @@ struct QSWAP : public ContractBase uint128 feeToShareholders; uint128 feeToQx; uint128 feeToBurn; + + sint64 totalFee; }; // https://docs.uniswap.org/contracts/v2/reference/smart-contracts/router-02#swaptokensforexacttokens @@ -1708,21 +1709,7 @@ struct QSWAP : public ContractBase ); // above call overflow - if (locals.quAmountIn == -1) - { - qpi.transfer(qpi.invocator(), qpi.invocationReward()); - return; - } - - // not enough qu amountIn - if (locals.quAmountIn > qpi.invocationReward()) - { - qpi.transfer(qpi.invocator(), qpi.invocationReward()); - return; - } - - // not meet user's amountIn limit - if (locals.quAmountIn > qpi.invocationReward()) + if (locals.quAmountIn == -1 || locals.quAmountIn > qpi.invocationReward()) { qpi.transfer(qpi.invocator(), qpi.invocationReward()); return; @@ -1736,6 +1723,13 @@ struct QSWAP : public ContractBase locals.feeToInvestRewards = div(locals.swapFee * uint128(state.investRewardsFeeRate), uint128(QSWAP_FEE_BASE_100)); locals.feeToBurn = div(locals.swapFee * uint128(state.burnFeeRate), uint128(QSWAP_FEE_BASE_100)); + locals.totalFee = sint64(locals.feeToShareholders.low) + sint64(locals.feeToQx.low) + sint64(locals.feeToInvestRewards.low) + sint64(locals.feeToBurn.low); + if (locals.quAmountIn < locals.totalFee) + { + qpi.transfer(qpi.invocator(), locals.quAmountIn); + return; + } + // Overflow protection: ensure all fees fit in uint64 if (locals.feeToShareholders.high != 0 || locals.feeToQx.high != 0 || locals.feeToInvestRewards.high != 0 || locals.feeToBurn.high != 0) @@ -1773,7 +1767,7 @@ struct QSWAP : public ContractBase state.investRewardsEarnedFee += locals.feeToInvestRewards.low; state.burnEarnedFee += locals.feeToBurn.low; - locals.poolBasicState.reservedQuAmount += locals.quAmountIn - sint64(locals.feeToShareholders.low) - sint64(locals.feeToQx.low) - sint64(locals.feeToInvestRewards.low) - sint64(locals.feeToBurn.low); + locals.poolBasicState.reservedQuAmount += locals.quAmountIn - locals.totalFee; locals.poolBasicState.reservedAssetAmount -= input.assetAmountOut; state.mPoolBasicStates.set(locals.poolSlot, locals.poolBasicState); @@ -1805,6 +1799,8 @@ struct QSWAP : public ContractBase uint128 feeToShareholders; uint128 feeToQx; uint128 feeToBurn; + + sint64 totalFee; }; // given an amount of asset swap in, only execute swaping if quAmountOut >= input.amountOutMin @@ -1960,11 +1956,15 @@ struct QSWAP : public ContractBase // update pool states locals.poolBasicState.reservedAssetAmount += input.assetAmountIn; - locals.poolBasicState.reservedQuAmount -= locals.quAmountOut; - locals.poolBasicState.reservedQuAmount -= sint64(locals.feeToShareholders.low); - locals.poolBasicState.reservedQuAmount -= sint64(locals.feeToQx.low); - locals.poolBasicState.reservedQuAmount -= sint64(locals.feeToInvestRewards.low); - locals.poolBasicState.reservedQuAmount -= sint64(locals.feeToBurn.low); + locals.totalFee = locals.quAmountOut + sint64(locals.feeToShareholders.low) + sint64(locals.feeToQx.low) + sint64(locals.feeToInvestRewards.low) + sint64(locals.feeToBurn.low); + if (locals.poolBasicState.reservedQuAmount < locals.totalFee) + { + locals.poolBasicState.reservedQuAmount = 0; + } + else + { + locals.poolBasicState.reservedQuAmount -= locals.totalFee; + } state.mPoolBasicStates.set(locals.poolSlot, locals.poolBasicState); // Log SwapExactAssetForQu procedure @@ -1994,6 +1994,8 @@ struct QSWAP : public ContractBase uint128 feeToShareholders; uint128 feeToQx; uint128 feeToBurn; + + sint64 totalFee; }; PUBLIC_PROCEDURE_WITH_LOCALS(SwapAssetForExactQu) @@ -2145,11 +2147,15 @@ struct QSWAP : public ContractBase // update pool states locals.poolBasicState.reservedAssetAmount += locals.assetAmountIn; - locals.poolBasicState.reservedQuAmount -= input.quAmountOut; - locals.poolBasicState.reservedQuAmount -= sint64(locals.feeToShareholders.low); - locals.poolBasicState.reservedQuAmount -= sint64(locals.feeToQx.low); - locals.poolBasicState.reservedQuAmount -= sint64(locals.feeToInvestRewards.low); - locals.poolBasicState.reservedQuAmount -= sint64(locals.feeToBurn.low); + locals.totalFee = input.quAmountOut + sint64(locals.feeToShareholders.low) + sint64(locals.feeToQx.low) + sint64(locals.feeToInvestRewards.low) + sint64(locals.feeToBurn.low); + if (locals.poolBasicState.reservedQuAmount < locals.totalFee) + { + locals.poolBasicState.reservedQuAmount = 0; + } + else + { + locals.poolBasicState.reservedQuAmount -= locals.totalFee; + } state.mPoolBasicStates.set(locals.poolSlot, locals.poolBasicState); // Log SwapAssetForExactQu procedure @@ -2162,19 +2168,11 @@ struct QSWAP : public ContractBase LOG_INFO(locals.swapMessage); } - struct TransferShareOwnershipAndPossession_locals - { - QX::Fees_input feesInput; - QX::Fees_output feesOutput; - }; - - PUBLIC_PROCEDURE_WITH_LOCALS(TransferShareOwnershipAndPossession) + PUBLIC_PROCEDURE(TransferShareOwnershipAndPossession) { output.transferredAmount = 0; - CALL_OTHER_CONTRACT_FUNCTION(QX, Fees, locals.feesInput, locals.feesOutput); - - if (qpi.invocationReward() < locals.feesOutput.transferFee) + if (qpi.invocationReward() < state.cachedTransferFee) { qpi.transfer(qpi.invocator(), qpi.invocationReward()); return; @@ -2221,11 +2219,11 @@ struct QSWAP : public ContractBase } else { - if (qpi.invocationReward() > locals.feesOutput.transferFee) + if (qpi.invocationReward() > state.cachedTransferFee) { - qpi.transfer(qpi.invocator(), qpi.invocationReward() - locals.feesOutput.transferFee); + qpi.transfer(qpi.invocator(), qpi.invocationReward() - state.cachedTransferFee); } - state.shareholderEarnedFee += locals.feesOutput.transferFee; + state.shareholderEarnedFee += state.cachedTransferFee; } } @@ -2241,43 +2239,57 @@ struct QSWAP : public ContractBase output.success = true; } - PUBLIC_PROCEDURE(TransferShareManagementRights) + struct TransferShareManagementRights_locals { - if (qpi.invocationReward() < QSWAP_FEE_BASE_100) - { - return ; - } + sint64 result; + sint64 reward; + sint64 refundAmount; + sint64 requiredFee; + bit success; + }; - if (qpi.numberOfPossessedShares(input.asset.assetName, input.asset.issuer,qpi.invocator(), qpi.invocator(), SELF_INDEX, SELF_INDEX) < input.numberOfShares) + PUBLIC_PROCEDURE_WITH_LOCALS(TransferShareManagementRights) + { + locals.reward = qpi.invocationReward(); + locals.refundAmount = locals.reward; + + output.transferredNumberOfShares = 0; + + locals.success = false; + + if (qpi.numberOfPossessedShares( + input.asset.assetName, + input.asset.issuer, + qpi.invocator(), + qpi.invocator(), + SELF_INDEX, + SELF_INDEX) >= input.numberOfShares) { - // not enough shares available - output.transferredNumberOfShares = 0; - if (qpi.invocationReward() > 0) + locals.result = qpi.releaseShares( + input.asset, + qpi.invocator(), + qpi.invocator(), + input.numberOfShares, + input.newManagingContractIndex, + input.newManagingContractIndex, + locals.reward + ); + + if (locals.result != INVALID_AMOUNT && locals.result >= 0) { - qpi.transfer(qpi.invocator(), qpi.invocationReward()); + locals.success = true; + locals.refundAmount = locals.reward - locals.result; } } - else + + if (locals.success) { - if (qpi.releaseShares(input.asset, qpi.invocator(), qpi.invocator(), input.numberOfShares, - input.newManagingContractIndex, input.newManagingContractIndex, QSWAP_FEE_BASE_100) < 0) - { - // error - output.transferredNumberOfShares = 0; - if (qpi.invocationReward() > 0) - { - qpi.transfer(qpi.invocator(), qpi.invocationReward()); - } - } - else - { - // success - output.transferredNumberOfShares = input.numberOfShares; - if (qpi.invocationReward() > QSWAP_FEE_BASE_100) - { - qpi.transfer(qpi.invocator(), qpi.invocationReward() - QSWAP_FEE_BASE_100); - } - } + output.transferredNumberOfShares = input.numberOfShares; + } + + if (locals.refundAmount > 0) + { + qpi.transfer(qpi.invocator(), locals.refundAmount); } } @@ -2318,10 +2330,29 @@ struct QSWAP : public ContractBase state.qxFeeRate = 5; // 5% of swap fees to QX state.burnFeeRate = 1; // 1% of swap fees burned + ASSERT(state.swapFeeRate < QSWAP_SWAP_FEE_BASE); + ASSERT(state.shareholderFeeRate + state.investRewardsFeeRate + state.qxFeeRate + state.burnFeeRate <= 100); // state.investRewardsId = ID(_V, _J, _G, _R, _U, _F, _W, _J, _C, _U, _S, _N, _H, _C, _Q, _J, _R, _W, _R, _R, _Y, _X, _A, _U, _E, _J, _F, _C, _V, _H, _Y, _P, _X, _W, _K, _T, _D, _L, _Y, _K, _U, _A, _C, _P, _V, _V, _Y, _B, _G, _O, _L, _V, _C, _J, _S, _F); } + struct BEGIN_EPOCH_locals + { + QX::Fees_input feesInput; + QX::Fees_output feesOutput; + }; + + BEGIN_EPOCH_WITH_LOCALS() + { + CALL_OTHER_CONTRACT_FUNCTION(QX, Fees, locals.feesInput, locals.feesOutput); + + if (interContractCallError == NoCallError) + { + state.cachedIssuanceFee = locals.feesOutput.assetIssuanceFee; + state.cachedTransferFee = locals.feesOutput.transferFee; + } + } + struct END_TICK_locals { uint64 toDistribute; @@ -2385,6 +2416,7 @@ struct QSWAP : public ContractBase state.burnedAmount += locals.toBurn; } } + PRE_ACQUIRE_SHARES() { output.allowTransfer = true; diff --git a/src/contracts/SupplyWatcher_old.h b/src/contracts/SupplyWatcher_old.h deleted file mode 100644 index 087291c9e..000000000 --- a/src/contracts/SupplyWatcher_old.h +++ /dev/null @@ -1,30 +0,0 @@ -using namespace QPI; - -struct SWATCH2 -{ -}; - -struct SWATCH : public ContractBase -{ - REGISTER_USER_FUNCTIONS_AND_PROCEDURES() - { - } - - struct BEGIN_EPOCH_locals - { - Entity ownEntity; - sint64 ownBalance; - }; - - BEGIN_EPOCH_WITH_LOCALS() - { - // Burn all coins of this contract. According to agreement of the quorum, a part of the - // computor revenue is donated to this contract for burning. - if (qpi.getEntity(SELF, locals.ownEntity)) - { - locals.ownBalance = locals.ownEntity.incomingAmount - locals.ownEntity.outgoingAmount; - if (locals.ownBalance > 0) - qpi.burn(locals.ownBalance); - } - } -}; diff --git a/src/contracts/qpi.h b/src/contracts/qpi.h index cfd2e697a..0a57ce0df 100644 --- a/src/contracts/qpi.h +++ b/src/contracts/qpi.h @@ -2801,23 +2801,23 @@ namespace QPI #define LOG_RESUME() __resumeLogMessage(); #define PRIVATE_FUNCTION(function) \ - private: \ + protected: \ typedef QPI::NoData function##_locals; \ PRIVATE_FUNCTION_WITH_LOCALS(function) #define PRIVATE_FUNCTION_WITH_LOCALS(function) \ - private: \ + protected: \ enum { __is_function_##function = true }; \ inline static void function(const QPI::QpiContextFunctionCall& qpi, const CONTRACT_STATE_TYPE& state, function##_input& input, function##_output& output, function##_locals& locals) { ::__FunctionOrProcedureBeginEndGuard<(CONTRACT_INDEX << 22) | __LINE__> __prologueEpilogueCaller; __impl_##function(qpi, state, input, output, locals); } \ static void __impl_##function(const QPI::QpiContextFunctionCall& qpi, const CONTRACT_STATE_TYPE& state, function##_input& input, function##_output& output, function##_locals& locals) #define PRIVATE_PROCEDURE(procedure) \ - private: \ + protected: \ typedef QPI::NoData procedure##_locals; \ PRIVATE_PROCEDURE_WITH_LOCALS(procedure) #define PRIVATE_PROCEDURE_WITH_LOCALS(procedure) \ - private: \ + protected: \ enum { __is_function_##procedure = false }; \ inline static void procedure(const QPI::QpiContextProcedureCall& qpi, CONTRACT_STATE_TYPE& state, procedure##_input& input, procedure##_output& output, procedure##_locals& locals) { ::__FunctionOrProcedureBeginEndGuard<(CONTRACT_INDEX << 22) | __LINE__> __prologueEpilogueCaller; __impl_##procedure(qpi, state, input, output, locals); } \ static void __impl_##procedure(const QPI::QpiContextProcedureCall& qpi, CONTRACT_STATE_TYPE& state, procedure##_input& input, procedure##_output& output, procedure##_locals& locals) diff --git a/src/public_settings.h b/src/public_settings.h index 3df5ff134..668330fa8 100644 --- a/src/public_settings.h +++ b/src/public_settings.h @@ -66,12 +66,12 @@ static_assert(AUTO_FORCE_NEXT_TICK_THRESHOLD* TARGET_TICK_DURATION >= PEER_REFRE // Config options that should NOT be changed by operators #define VERSION_A 1 -#define VERSION_B 276 +#define VERSION_B 277 #define VERSION_C 0 // Epoch and initial tick for node startup -#define EPOCH 198 -#define TICK 43101000 +#define EPOCH 199 +#define TICK 43493000 #define TICK_IS_FIRST_TICK_OF_EPOCH 1 // Set to 0 if the network is restarted during the EPOCH with a new initial TICK #define ARBITRATOR "AFZPUAIYVPNUYGJRQVLUKOPPVLHAZQTGLYAAUUNBXFTVTAMSBKQBLEIEPCVJ" @@ -102,7 +102,11 @@ static constexpr unsigned long long ADDITION_NUMBER_OF_TICKS = 1000; static constexpr unsigned long long ADDITION_NUMBER_OF_NEIGHBORS = 728; // 2M. Must be divided by 2 static constexpr unsigned long long ADDITION_NUMBER_OF_MUTATIONS = 150; static constexpr unsigned long long ADDITION_POPULATION_THRESHOLD = ADDITION_NUMBER_OF_INPUT_NEURONS + ADDITION_NUMBER_OF_OUTPUT_NEURONS + ADDITION_NUMBER_OF_MUTATIONS; // P -static constexpr unsigned int ADDITION_SOLUTION_THRESHOLD_DEFAULT = 74200; +static constexpr unsigned int ADDITION_SOLUTION_THRESHOLD_DEFAULT = 74194; + +// Multipler of score +static constexpr unsigned int HYPERIDENTITY_SOLUTION_MULTIPLER = 1; +static constexpr unsigned int ADDITION_SOLUTION_MULTIPLER = 1; static constexpr long long NEURON_VALUE_LIMIT = 1LL; diff --git a/src/qubic.cpp b/src/qubic.cpp index cbc2020c0..1e496cdc9 100644 --- a/src/qubic.cpp +++ b/src/qubic.cpp @@ -1,16 +1,5 @@ #define SINGLE_COMPILE_UNIT -// #define OLD_SWATCH -// #define NO_QRP -// #define NO_QTF -// #define NO_QDUEL - -// QTF in its current state is only usable with QRP. -// If the QRP proposal is rejected, disable QTF as well. -#if defined NO_QRP && !defined NO_QTF -#define NO_QTF -#endif - // contract_def.h needs to be included first to make sure that contracts have minimal access #include "contract_core/contract_def.h" #include "contract_core/contract_exec.h" @@ -211,6 +200,11 @@ static unsigned long long K12MeasurementsCount = 0; static unsigned long long K12MeasurementsSum = 0; static volatile char minerScoreArrayLock = 0; static SpecialCommandGetMiningScoreRanking requestMiningScoreRanking; +static constexpr unsigned int gScoreMultiplier[score_engine::AlgoType::MaxAlgoCount] = +{ + HYPERIDENTITY_SOLUTION_MULTIPLER, // HyperIdentity + ADDITION_SOLUTION_MULTIPLER // Addition +}; // Custom mining related variables and constants static unsigned int gCustomMiningSharesCount[NUMBER_OF_COMPUTORS] = { 0 }; @@ -2645,7 +2639,7 @@ static void processTickTransactionSolution(const MiningSolutionTransaction* tran { if (transaction->sourcePublicKey == minerPublicKeys[minerIndex]) { - minerScores[minerIndex]++; + minerScores[minerIndex] += gScoreMultiplier[selectedAlgo]; break; } @@ -2654,7 +2648,7 @@ static void processTickTransactionSolution(const MiningSolutionTransaction* tran && numberOfMiners < MAX_NUMBER_OF_MINERS) { minerPublicKeys[numberOfMiners] = transaction->sourcePublicKey; - minerScores[numberOfMiners++] = 1; + minerScores[numberOfMiners++] = gScoreMultiplier[selectedAlgo]; } const m256i tmpPublicKey = minerPublicKeys[minerIndex]; diff --git a/test/contract_qduel.cpp b/test/contract_qduel.cpp index 161949366..e06af0a67 100644 --- a/test/contract_qduel.cpp +++ b/test/contract_qduel.cpp @@ -1,9 +1,6 @@ #define NO_UEFI -#define _ALLOW_KEYWORD_MACROS -#define private protected + #include "contract_testing.h" -#undef private -#undef _ALLOW_KEYWORD_MACROS constexpr uint16 PROCEDURE_INDEX_CREATE_ROOM = 1; constexpr uint16 PROCEDURE_INDEX_CONNECT_ROOM = 2; diff --git a/test/contract_qswap.cpp b/test/contract_qswap.cpp index 1fe164eab..4b9ef09b0 100644 --- a/test/contract_qswap.cpp +++ b/test/contract_qswap.cpp @@ -58,6 +58,11 @@ class ContractTestingQswap : protected ContractTesting return (QswapChecker*)contractStates[QSWAP_CONTRACT_INDEX]; } + void beginEpoch(bool expectSuccess = true) + { + callSystemProcedure(QSWAP_CONTRACT_INDEX, BEGIN_EPOCH, expectSuccess); + } + bool loadState(const CHAR16* filename) { return load(filename, sizeof(QSWAP), contractStates[QSWAP_CONTRACT_INDEX]) == sizeof(QSWAP); @@ -334,6 +339,7 @@ TEST(ContractSwap, QuoteTest) TEST(ContractSwap, IssueAssetAndTransferShareManagementRights) { ContractTestingQswap qswap; + qswap.beginEpoch(); id issuer(1, 2, 3, 4); diff --git a/test/contract_qtf.cpp b/test/contract_qtf.cpp index 9ecd05747..c9427156d 100644 --- a/test/contract_qtf.cpp +++ b/test/contract_qtf.cpp @@ -1,11 +1,6 @@ #define NO_UEFI -#define _ALLOW_KEYWORD_MACROS 1 - -#define private protected #include "contract_testing.h" -#undef private -#undef _ALLOW_KEYWORD_MACROS #include #include