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