diff --git a/src/Qubic.vcxproj b/src/Qubic.vcxproj
index 27c41c20..63046690 100644
--- a/src/Qubic.vcxproj
+++ b/src/Qubic.vcxproj
@@ -23,6 +23,7 @@
+
diff --git a/src/Qubic.vcxproj.filters b/src/Qubic.vcxproj.filters
index 94918128..2e3899a1 100644
--- a/src/Qubic.vcxproj.filters
+++ b/src/Qubic.vcxproj.filters
@@ -116,7 +116,7 @@
contracts
- contracts
+ contracts
contract_core
@@ -211,6 +211,9 @@
platform
+
+ contracts
+
diff --git a/src/assets/assets.h b/src/assets/assets.h
index 96b135e0..e693cfaa 100644
--- a/src/assets/assets.h
+++ b/src/assets/assets.h
@@ -28,7 +28,7 @@
// TODO: move this into AssetStorage class
GLOBAL_VAR_DECL volatile char universeLock GLOBAL_VAR_INIT(0);
-GLOBAL_VAR_DECL Asset* assets GLOBAL_VAR_INIT(nullptr);
+GLOBAL_VAR_DECL AssetRecord* assets GLOBAL_VAR_INIT(nullptr);
GLOBAL_VAR_DECL m256i* assetDigests GLOBAL_VAR_INIT(nullptr);
static constexpr unsigned long long assetDigestsSizeInBytes = (ASSETS_CAPACITY * 2 - 1) * 32ULL;
GLOBAL_VAR_DECL unsigned long long* assetChangeFlags GLOBAL_VAR_INIT(nullptr);
@@ -159,7 +159,7 @@ static unsigned int issuanceIndex(const m256i& issuer, unsigned long long assetN
static bool initAssets()
{
- if (!allocatePool(ASSETS_CAPACITY * sizeof(Asset), (void**)&assets)
+ if (!allocatePool(ASSETS_CAPACITY * sizeof(AssetRecord), (void**)&assets)
|| !allocatePool(assetDigestsSizeInBytes, (void**)&assetDigests)
|| !allocatePool(ASSETS_CAPACITY / 8, (void**)&assetChangeFlags))
{
@@ -276,7 +276,7 @@ static long long issueAsset(const m256i& issuerPublicKey, const char name[7], ch
}
static sint64 numberOfShares(
- const AssetIssuanceId& issuanceId,
+ const Asset& issuanceId,
const AssetOwnershipSelect& ownership = AssetOwnershipSelect::any(),
const AssetPossessionSelect& possession = AssetPossessionSelect::any())
{
@@ -505,7 +505,7 @@ static void getUniverseDigest(m256i& digest)
{
if (assetChangeFlags[digestIndex >> 6] & (1ULL << (digestIndex & 63)))
{
- KangarooTwelve(&assets[digestIndex], sizeof(Asset), &assetDigests[digestIndex], 32);
+ KangarooTwelve(&assets[digestIndex], sizeof(AssetRecord), &assetDigests[digestIndex], 32);
}
}
unsigned int previousLevelBeginning = 0;
@@ -538,10 +538,10 @@ static bool saveUniverse(const CHAR16* fileName = UNIVERSE_FILE_NAME, const CHAR
const unsigned long long beginningTick = __rdtsc();
ACQUIRE(universeLock);
- long long savedSize = save(fileName, ASSETS_CAPACITY * sizeof(Asset), (unsigned char*)assets, directory);
+ long long savedSize = save(fileName, ASSETS_CAPACITY * sizeof(AssetRecord), (unsigned char*)assets, directory);
RELEASE(universeLock);
- if (savedSize == ASSETS_CAPACITY * sizeof(Asset))
+ if (savedSize == ASSETS_CAPACITY * sizeof(AssetRecord))
{
setNumber(message, savedSize, TRUE);
appendText(message, L" bytes of the universe data are saved (");
@@ -555,8 +555,8 @@ static bool saveUniverse(const CHAR16* fileName = UNIVERSE_FILE_NAME, const CHAR
static bool loadUniverse(const CHAR16* fileName = UNIVERSE_FILE_NAME, CHAR16* directory = NULL)
{
- long long loadedSize = load(fileName, ASSETS_CAPACITY * sizeof(Asset), (unsigned char*)assets, directory);
- if (loadedSize != ASSETS_CAPACITY * sizeof(Asset))
+ long long loadedSize = load(fileName, ASSETS_CAPACITY * sizeof(AssetRecord), (unsigned char*)assets, directory);
+ if (loadedSize != ASSETS_CAPACITY * sizeof(AssetRecord))
{
logStatusToConsole(L"EFI_FILE_PROTOCOL.Read() reads invalid number of bytes", loadedSize, __LINE__);
@@ -571,8 +571,8 @@ static void assetsEndEpoch()
ACQUIRE(universeLock);
// rebuild asset hash map, getting rid of all elements with zero shares
- Asset* reorgAssets = (Asset*)reorgBuffer;
- setMem(reorgAssets, ASSETS_CAPACITY * sizeof(Asset), 0);
+ AssetRecord* reorgAssets = (AssetRecord*)reorgBuffer;
+ setMem(reorgAssets, ASSETS_CAPACITY * sizeof(AssetRecord), 0);
for (unsigned int i = 0; i < ASSETS_CAPACITY; i++)
{
if (assets[i].varStruct.possession.type == POSSESSION
@@ -591,7 +591,7 @@ static void assetsEndEpoch()
{
if (reorgAssets[issuanceIndex].varStruct.issuance.type == EMPTY)
{
- copyMem(&reorgAssets[issuanceIndex], &assets[oldIssuanceIndex], sizeof(Asset));
+ copyMem(&reorgAssets[issuanceIndex], &assets[oldIssuanceIndex], sizeof(AssetRecord));
}
const m256i& ownerPublicKey = assets[oldOwnershipIndex].varStruct.ownership.publicKey;
@@ -651,7 +651,7 @@ static void assetsEndEpoch()
}
}
}
- copyMem(assets, reorgAssets, ASSETS_CAPACITY * sizeof(Asset));
+ copyMem(assets, reorgAssets, ASSETS_CAPACITY * sizeof(AssetRecord));
setMem(assetChangeFlags, ASSETS_CAPACITY / 8, 0xFF);
diff --git a/src/assets/net_msg_impl.h b/src/assets/net_msg_impl.h
index 2cbcb8b6..96a6a1c4 100644
--- a/src/assets/net_msg_impl.h
+++ b/src/assets/net_msg_impl.h
@@ -25,7 +25,7 @@ static void processRequestIssuedAssets(Peer* peer, RequestResponseHeader* header
if (assets[universeIndex].varStruct.issuance.type == ISSUANCE
&& assets[universeIndex].varStruct.issuance.publicKey == request->publicKey)
{
- bs->CopyMem(&response.asset, &assets[universeIndex], sizeof(Asset));
+ bs->CopyMem(&response.asset, &assets[universeIndex], sizeof(AssetRecord));
response.tick = system.tick;
response.universeIndex = universeIndex;
getSiblings(response.universeIndex, assetDigests, response.siblings);
@@ -62,8 +62,8 @@ static void processRequestOwnedAssets(Peer* peer, RequestResponseHeader* header)
if (assets[universeIndex].varStruct.issuance.type == OWNERSHIP
&& assets[universeIndex].varStruct.issuance.publicKey == request->publicKey)
{
- bs->CopyMem(&response.asset, &assets[universeIndex], sizeof(Asset));
- bs->CopyMem(&response.issuanceAsset, &assets[assets[universeIndex].varStruct.ownership.issuanceIndex], sizeof(Asset));
+ bs->CopyMem(&response.asset, &assets[universeIndex], sizeof(AssetRecord));
+ bs->CopyMem(&response.issuanceAsset, &assets[assets[universeIndex].varStruct.ownership.issuanceIndex], sizeof(AssetRecord));
response.tick = system.tick;
response.universeIndex = universeIndex;
getSiblings(response.universeIndex, assetDigests, response.siblings);
@@ -100,9 +100,9 @@ static void processRequestPossessedAssets(Peer* peer, RequestResponseHeader* hea
if (assets[universeIndex].varStruct.issuance.type == POSSESSION
&& assets[universeIndex].varStruct.issuance.publicKey == request->publicKey)
{
- bs->CopyMem(&response.asset, &assets[universeIndex], sizeof(Asset));
- bs->CopyMem(&response.ownershipAsset, &assets[assets[universeIndex].varStruct.possession.ownershipIndex], sizeof(Asset));
- bs->CopyMem(&response.issuanceAsset, &assets[assets[assets[universeIndex].varStruct.possession.ownershipIndex].varStruct.ownership.issuanceIndex], sizeof(Asset));
+ bs->CopyMem(&response.asset, &assets[universeIndex], sizeof(AssetRecord));
+ bs->CopyMem(&response.ownershipAsset, &assets[assets[universeIndex].varStruct.possession.ownershipIndex], sizeof(AssetRecord));
+ bs->CopyMem(&response.issuanceAsset, &assets[assets[assets[universeIndex].varStruct.possession.ownershipIndex].varStruct.ownership.issuanceIndex], sizeof(AssetRecord));
response.tick = system.tick;
response.universeIndex = universeIndex;
getSiblings(response.universeIndex, assetDigests, response.siblings);
diff --git a/src/common_buffers.h b/src/common_buffers.h
index 89eea93d..4868c83d 100644
--- a/src/common_buffers.h
+++ b/src/common_buffers.h
@@ -8,7 +8,7 @@
constexpr unsigned long long spectrumSizeInBytes = SPECTRUM_CAPACITY * sizeof(::Entity);
-constexpr unsigned long long universeSizeInBytes = ASSETS_CAPACITY * sizeof(Asset);
+constexpr unsigned long long universeSizeInBytes = ASSETS_CAPACITY * sizeof(AssetRecord);
// Buffer used for reorganizing spectrum and universe hash maps, currently also used as scratchpad buffer for contracts
// Must be large enough to fit any contract, full spectrum, and full universe!
diff --git a/src/contract_core/contract_def.h b/src/contract_core/contract_def.h
index 9826c336..d022bba6 100644
--- a/src/contract_core/contract_def.h
+++ b/src/contract_core/contract_def.h
@@ -149,7 +149,11 @@ struct __FunctionOrProcedureBeginEndGuard
#define CONTRACT_INDEX QEARN_CONTRACT_INDEX
#define CONTRACT_STATE_TYPE QEARN
#define CONTRACT_STATE2_TYPE QEARN2
+#ifdef QEARN_UPDATE
#include "contracts/Qearn.h"
+#else
+#include "contracts/Qearn_old.h"
+#endif
#undef CONTRACT_INDEX
#undef CONTRACT_STATE_TYPE
diff --git a/src/contract_core/qpi_asset_impl.h b/src/contract_core/qpi_asset_impl.h
index 462d4456..2887c93f 100644
--- a/src/contract_core/qpi_asset_impl.h
+++ b/src/contract_core/qpi_asset_impl.h
@@ -7,7 +7,7 @@
// Start iteration with given issuance and given ownership filter (selects first record).
-void QPI::AssetOwnershipIterator::begin(const QPI::AssetIssuanceId& issuance, const QPI::AssetOwnershipSelect& ownership)
+void QPI::AssetOwnershipIterator::begin(const QPI::Asset& issuance, const QPI::AssetOwnershipSelect& ownership)
{
_issuance = issuance;
_issuanceIdx = ::issuanceIndex(issuance.issuer, issuance.assetName);
@@ -125,7 +125,7 @@ sint64 QPI::AssetOwnershipIterator::numberOfOwnedShares() const
// Start iteration with given issuance and given ownership + possession filters (selects first record).
-void QPI::AssetPossessionIterator::begin(const AssetIssuanceId& issuance, const AssetOwnershipSelect& ownership, const AssetPossessionSelect& possession)
+void QPI::AssetPossessionIterator::begin(const Asset& issuance, const AssetOwnershipSelect& ownership, const AssetPossessionSelect& possession)
{
AssetOwnershipIterator::begin(issuance, ownership);
@@ -433,7 +433,7 @@ long long QPI::QpiContextFunctionCall::numberOfPossessedShares(unsigned long lon
return ::numberOfPossessedShares(assetName, issuer, owner, possessor, ownershipManagingContractIndex, possessionManagingContractIndex);
}
-sint64 QPI::QpiContextFunctionCall::numberOfShares(const QPI::AssetIssuanceId& issuanceId, const QPI::AssetOwnershipSelect& ownership, const QPI::AssetPossessionSelect& possession) const
+sint64 QPI::QpiContextFunctionCall::numberOfShares(const QPI::Asset& issuanceId, const QPI::AssetOwnershipSelect& ownership, const QPI::AssetPossessionSelect& possession) const
{
return ::numberOfShares(issuanceId, ownership, possession);
}
diff --git a/src/contract_core/qpi_collection_impl.h b/src/contract_core/qpi_collection_impl.h
index c96b23d3..8c8282dd 100644
--- a/src/contract_core/qpi_collection_impl.h
+++ b/src/contract_core/qpi_collection_impl.h
@@ -1,4 +1,4 @@
-// Implements functions of QPI::collection in order to:
+// Implements functions of QPI::Collection in order to:
// 1. keep setMem() and copyMem() unavailable to contracts
// 2. keep QPI file smaller and easier to read for contract devs
// CAUTION: Include this AFTER the contract implementations!
@@ -11,7 +11,7 @@
namespace QPI
{
template
- void collection::_softReset()
+ void Collection::_softReset()
{
setMem(_povs, sizeof(_povs), 0);
setMem(_povOccupationFlags, sizeof(_povOccupationFlags), 0);
@@ -20,7 +20,7 @@ namespace QPI
}
template
- sint64 collection::_povIndex(const id& pov) const
+ sint64 Collection::_povIndex(const id& pov) const
{
sint64 povIndex = pov.u64._0 & (L - 1);
for (sint64 counter = 0; counter < L; counter += 32)
@@ -46,7 +46,7 @@ namespace QPI
}
template
- sint64 collection::_headIndex(const sint64 povIndex, const sint64 maxPriority) const
+ sint64 Collection::_headIndex(const sint64 povIndex, const sint64 maxPriority) const
{
// with current code path, pov is not empty here
const auto& pov = _povs[povIndex];
@@ -95,7 +95,7 @@ namespace QPI
}
template
- sint64 collection::_tailIndex(const sint64 povIndex, const sint64 minPriority) const
+ sint64 Collection::_tailIndex(const sint64 povIndex, const sint64 minPriority) const
{
// with current code path, pov is not empty here
const auto& pov = _povs[povIndex];
@@ -145,7 +145,7 @@ namespace QPI
}
template
- sint64 collection::_searchElement(const sint64 bstRootIndex,
+ sint64 Collection::_searchElement(const sint64 bstRootIndex,
const sint64 priority, int* pIterationsCount) const
{
sint64 idx = bstRootIndex;
@@ -183,7 +183,7 @@ namespace QPI
}
template
- sint64 collection::_addPovElement(const sint64 povIndex, const T value, const sint64 priority)
+ sint64 Collection::_addPovElement(const sint64 povIndex, const T value, const sint64 priority)
{
const sint64 newElementIdx = _population++;
auto& newElement = _elements[newElementIdx].init(value, priority, povIndex);
@@ -230,7 +230,7 @@ namespace QPI
}
template
- uint64 collection::_getSortedElements(const sint64 rootIdx, sint64* sortedElementIndices) const
+ uint64 Collection::_getSortedElements(const sint64 rootIdx, sint64* sortedElementIndices) const
{
uint64 count = 0;
sint64 elementIdx = rootIdx;
@@ -269,7 +269,7 @@ namespace QPI
}
template
- inline void collection::_set(sint64_4& vec, sint64 v0, sint64 v1, sint64 v2, sint64 v3) const
+ inline void Collection::_set(sint64_4& vec, sint64 v0, sint64 v1, sint64 v2, sint64 v3) const
{
vec.set(0, v0);
vec.set(1, v1);
@@ -278,7 +278,7 @@ namespace QPI
}
template
- sint64 collection::_rebuild(sint64 rootIdx)
+ sint64 Collection::_rebuild(sint64 rootIdx)
{
auto* sortedElementIndices = reinterpret_cast(::__scratchpad());
if (sortedElementIndices == NULL)
@@ -364,7 +364,7 @@ namespace QPI
}
template
- sint64 collection::_getMostLeft(sint64 elementIdx) const
+ sint64 Collection::_getMostLeft(sint64 elementIdx) const
{
while (_elements[elementIdx].bstLeftIndex != NULL_INDEX)
{
@@ -374,7 +374,7 @@ namespace QPI
}
template
- sint64 collection::_getMostRight(sint64 elementIdx) const
+ sint64 Collection::_getMostRight(sint64 elementIdx) const
{
while (_elements[elementIdx].bstRightIndex != NULL_INDEX)
{
@@ -384,7 +384,7 @@ namespace QPI
}
template
- sint64 collection::_previousElementIndex(sint64 elementIdx) const
+ sint64 Collection::_previousElementIndex(sint64 elementIdx) const
{
elementIdx &= (L - 1);
if (uint64(elementIdx) < _population)
@@ -415,7 +415,7 @@ namespace QPI
}
template
- sint64 collection::_nextElementIndex(sint64 elementIdx) const
+ sint64 Collection::_nextElementIndex(sint64 elementIdx) const
{
elementIdx &= (L - 1);
if (uint64(elementIdx) < _population)
@@ -446,7 +446,7 @@ namespace QPI
}
template
- bool collection::_updateParent(const sint64 elementIdx, const sint64 newElementIdx)
+ bool Collection::_updateParent(const sint64 elementIdx, const sint64 newElementIdx)
{
if (elementIdx != NULL_INDEX)
{
@@ -473,7 +473,7 @@ namespace QPI
}
template
- void collection::_moveElement(const sint64 srcIdx, const sint64 dstIdx)
+ void Collection::_moveElement(const sint64 srcIdx, const sint64 dstIdx)
{
copyMem(&_elements[dstIdx], &_elements[srcIdx], sizeof(_elements[0]));
@@ -516,7 +516,7 @@ namespace QPI
}
template
- uint64 collection::_getEncodedPovOccupationFlags(const uint64* povOccupationFlags, const sint64 povIndex) const
+ uint64 Collection::_getEncodedPovOccupationFlags(const uint64* povOccupationFlags, const sint64 povIndex) const
{
const sint64 offset = (povIndex & 31) << 1;
uint64 flags = povOccupationFlags[povIndex >> 5] >> offset;
@@ -528,7 +528,7 @@ namespace QPI
}
template
- sint64 collection::add(const id& pov, T element, sint64 priority)
+ sint64 Collection::add(const id& pov, T element, sint64 priority)
{
if (_population < capacity() && _markRemovalCounter < capacity())
{
@@ -562,12 +562,12 @@ namespace QPI
}
template
- void collection::cleanup()
+ void Collection::cleanup()
{
// _povs gets occupied over time with entries of type 3 which means they are marked for cleanup.
- // Once cleanup is called it's necessary to remove all these type 3 entries by reconstructing a fresh collection residing in scratchpad buffer.
+ // Once cleanup is called it's necessary to remove all these type 3 entries by reconstructing a fresh Collection residing in scratchpad buffer.
// The _elements array is not reorganized by the cleanup (only references to _povs are updated).
- // Cleanup() called for a collection having only type 3 entries in _povs must give the result equal to reset() memory content wise.
+ // Cleanup() called for a Collection having only type 3 entries in _povs must give the result equal to reset() memory content wise.
// Quick check to cleanup
if (!_markRemovalCounter)
@@ -575,7 +575,7 @@ namespace QPI
return;
}
- // Speedup case of empty collection but existed marked for removal povs
+ // Speedup case of empty Collection but existed marked for removal povs
if (!population())
{
_softReset();
@@ -590,7 +590,7 @@ namespace QPI
setMem(::__scratchpad(), sizeof(_povs) + sizeof(_povOccupationFlags), 0);
uint64 newPopulation = 0;
- // Go through pov hash map. For each pov that is occupied but not marked for removal, insert pov in new collection's pov buffers and
+ // Go through pov hash map. For each pov that is occupied but not marked for removal, insert pov in new Collection's pov buffers and
// update povIndex in elements belonging to pov.
constexpr uint64 oldPovIndexGroupCount = (L >> 5) ? (L >> 5) : 1;
for (sint64 oldPovIndexGroup = 0; oldPovIndexGroup < oldPovIndexGroupCount; oldPovIndexGroup++)
@@ -603,7 +603,7 @@ namespace QPI
for (maskBits >>= oldPovIndexOffset;
oldPovIndexOffset < oldPovIndexOffsetEnd; oldPovIndexOffset += 2, maskBits >>= 2)
{
- // Only add pov to new collection that are occupied and not marked for removal
+ // Only add pov to new Collection that are occupied and not marked for removal
if (maskBits & 3ULL)
{
// find empty position in new pov hash map
@@ -674,13 +674,13 @@ namespace QPI
}
template
- inline T collection::element(sint64 elementIndex) const
+ inline T Collection::element(sint64 elementIndex) const
{
return _elements[elementIndex & (L - 1)].value;
}
template
- sint64 collection::headIndex(const id& pov) const
+ sint64 Collection::headIndex(const id& pov) const
{
const sint64 povIndex = _povIndex(pov);
@@ -688,7 +688,7 @@ namespace QPI
}
template
- sint64 collection::headIndex(const id& pov, sint64 maxPriority) const
+ sint64 Collection::headIndex(const id& pov, sint64 maxPriority) const
{
const sint64 povIndex = _povIndex(pov);
if (povIndex < 0)
@@ -700,19 +700,19 @@ namespace QPI
}
template
- sint64 collection::nextElementIndex(sint64 elementIndex) const
+ sint64 Collection::nextElementIndex(sint64 elementIndex) const
{
return _nextElementIndex(elementIndex);
}
template
- inline uint64 collection::population() const
+ inline uint64 Collection::population() const
{
return _population;
}
template
- uint64 collection::population(const id& pov) const
+ uint64 Collection::population(const id& pov) const
{
const sint64 povIndex = _povIndex(pov);
@@ -720,25 +720,25 @@ namespace QPI
}
template
- id collection::pov(sint64 elementIndex) const
+ id Collection::pov(sint64 elementIndex) const
{
return _povs[_elements[elementIndex & (L - 1)].povIndex].value;
}
template
- sint64 collection::prevElementIndex(sint64 elementIndex) const
+ sint64 Collection::prevElementIndex(sint64 elementIndex) const
{
return _previousElementIndex(elementIndex);
}
template
- sint64 collection::priority(sint64 elementIndex) const
+ sint64 Collection::priority(sint64 elementIndex) const
{
return _elements[elementIndex & (L - 1)].priority;
}
template
- sint64 collection::remove(sint64 elementIdx)
+ sint64 Collection::remove(sint64 elementIdx)
{
sint64 nextElementIdxOfRemoved = NULL_INDEX;
elementIdx &= (L - 1);
@@ -853,7 +853,7 @@ namespace QPI
}
template
- void collection::replace(sint64 oldElementIndex, const T& newElement)
+ void Collection::replace(sint64 oldElementIndex, const T& newElement)
{
if (uint64(oldElementIndex) < _population)
{
@@ -862,13 +862,13 @@ namespace QPI
}
template
- void collection::reset()
+ void Collection::reset()
{
setMem(this, sizeof(*this), 0);
}
template
- sint64 collection::tailIndex(const id& pov) const
+ sint64 Collection::tailIndex(const id& pov) const
{
const sint64 povIndex = _povIndex(pov);
@@ -876,7 +876,7 @@ namespace QPI
}
template
- sint64 collection::tailIndex(const id& pov, sint64 minPriority) const
+ sint64 Collection::tailIndex(const id& pov, sint64 minPriority) const
{
const sint64 povIndex = _povIndex(pov);
if (povIndex < 0)
diff --git a/src/contract_core/qpi_trivial_impl.h b/src/contract_core/qpi_trivial_impl.h
index d77a589d..d61e7afc 100644
--- a/src/contract_core/qpi_trivial_impl.h
+++ b/src/contract_core/qpi_trivial_impl.h
@@ -23,14 +23,14 @@ namespace QPI
// Check if array is sorted in given range (duplicates allowed). Returns false if range is invalid.
template
- bool isArraySorted(const array& array, uint64 beginIdx, uint64 endIdx)
+ bool isArraySorted(const Array& Array, uint64 beginIdx, uint64 endIdx)
{
if (endIdx > L || beginIdx > endIdx)
return false;
for (uint64 i = beginIdx + 1; i < endIdx; ++i)
{
- if (array.get(i - 1) > array.get(i))
+ if (Array.get(i - 1) > Array.get(i))
return false;
}
@@ -39,14 +39,14 @@ namespace QPI
// Check if array is sorted without duplicates in given range. Returns false if range is invalid.
template
- bool isArraySortedWithoutDuplicates(const array& array, uint64 beginIdx, uint64 endIdx)
+ bool isArraySortedWithoutDuplicates(const Array& Array, uint64 beginIdx, uint64 endIdx)
{
if (endIdx > L || beginIdx > endIdx)
return false;
for (uint64 i = beginIdx + 1; i < endIdx; ++i)
{
- if (array.get(i - 1) >= array.get(i))
+ if (Array.get(i - 1) >= Array.get(i))
return false;
}
diff --git a/src/contracts/ComputorControlledFund.h b/src/contracts/ComputorControlledFund.h
index 49ccf645..2c3a44fe 100644
--- a/src/contracts/ComputorControlledFund.h
+++ b/src/contracts/ComputorControlledFund.h
@@ -27,13 +27,13 @@ struct CCF : public ContractBase
struct LatestTransfersEntry
{
id destination;
- array url;
+ Array url;
sint64 amount;
uint32 tick;
bool success;
};
- typedef array LatestTransfersT;
+ typedef Array LatestTransfersT;
private:
//----------------------------------------------------------------------------
@@ -102,7 +102,7 @@ struct CCF : public ContractBase
struct GetProposalIndices_output
{
uint16 numOfIndices; // Number of valid entries in indices. Call again if it is 64.
- array indices; // Requested proposal indices. Valid entries are in range 0 ... (numOfIndices - 1).
+ Array indices; // Requested proposal indices. Valid entries are in range 0 ... (numOfIndices - 1).
};
PUBLIC_FUNCTION(GetProposalIndices)
diff --git a/src/contracts/GeneralQuorumProposal.h b/src/contracts/GeneralQuorumProposal.h
index e0a41786..95df2bda 100644
--- a/src/contracts/GeneralQuorumProposal.h
+++ b/src/contracts/GeneralQuorumProposal.h
@@ -31,7 +31,7 @@ struct GQMPROP : public ContractBase
uint16 firstEpoch;
};
- typedef array RevenueDonationT;
+ typedef Array RevenueDonationT;
private:
//----------------------------------------------------------------------------
@@ -125,7 +125,7 @@ struct GQMPROP : public ContractBase
struct GetProposalIndices_output
{
uint16 numOfIndices; // Number of valid entries in indices. Call again if it is 64.
- array indices; // Requested proposal indices. Valid entries are in range 0 ... (numOfIndices - 1).
+ Array indices; // Requested proposal indices. Valid entries are in range 0 ... (numOfIndices - 1).
};
PUBLIC_FUNCTION(GetProposalIndices)
diff --git a/src/contracts/QVAULT.h b/src/contracts/QVAULT.h
index 77e848bd..8cbdf017 100644
--- a/src/contracts/QVAULT.h
+++ b/src/contracts/QVAULT.h
@@ -216,7 +216,7 @@ struct QVAULT : public ContractBase
id adminAddress, newAdminAddress1, newAdminAddress2, newAdminAddress3;
id bannedAddress1, bannedAddress2, bannedAddress3;
id unbannedAddress1, unbannedAddress2, unbannedAddress3;
- array bannedAddress;
+ Array bannedAddress;
uint32 numberOfBannedAddress;
uint32 shareholderDividend, QCAPHolderPermille, reinvestingPermille, devPermille, burnPermille;
uint32 newQCAPHolderPermille1, newReinvestingPermille1, newDevPermille1;
@@ -606,7 +606,7 @@ struct QVAULT : public ContractBase
{
::Entity entity;
AssetPossessionIterator iter;
- AssetIssuanceId QCAPId;
+ Asset QCAPId;
uint64 revenue;
uint64 paymentForShareholders;
uint64 paymentForQCAPHolders;
diff --git a/src/contracts/Qearn.h b/src/contracts/Qearn.h
index 513c8277..16cc52a6 100644
--- a/src/contracts/Qearn.h
+++ b/src/contracts/Qearn.h
@@ -171,6 +171,36 @@ struct QEARN : public ContractBase
};
+ struct getBurnedAndBoostedStats_input {
+
+ };
+
+ struct getBurnedAndBoostedStats_output {
+
+ uint64 burnedAmount;
+ uint64 averageBurnedPercent;
+ uint64 boostedAmount;
+ uint64 averageBoostedPercent;
+ uint64 rewardedAmount;
+ uint64 averageRewardedPercent;
+
+ };
+
+ struct getBurnedAndBoostedStatsPerEpoch_input {
+ uint32 epoch;
+ };
+
+ struct getBurnedAndBoostedStatsPerEpoch_output {
+
+ uint64 burnedAmount;
+ uint64 burnedPercent;
+ uint64 boostedAmount;
+ uint64 boostedPercent;
+ uint64 rewardedAmount;
+ uint64 rewardedPercent;
+
+ };
+
protected:
struct RoundInfo {
@@ -180,8 +210,8 @@ struct QEARN : public ContractBase
};
- array _initialRoundInfo;
- array _currentRoundInfo;
+ Array _initialRoundInfo;
+ Array _currentRoundInfo;
struct EpochIndexInfo {
@@ -189,7 +219,7 @@ struct QEARN : public ContractBase
uint32 endIndex;
};
- array _epochIndex;
+ Array _epochIndex;
struct LockInfo {
@@ -199,7 +229,7 @@ struct QEARN : public ContractBase
};
- array locker;
+ Array locker;
struct HistoryInfo {
@@ -209,12 +239,22 @@ struct QEARN : public ContractBase
};
- array earlyUnlocker;
- array fullyUnlocker;
+ Array earlyUnlocker;
+ Array fullyUnlocker;
uint32 _earlyUnlockedCnt;
uint32 _fullyUnlockedCnt;
+ struct StatsInfo {
+
+ uint64 burnedAmount;
+ uint64 boostedAmount;
+ uint64 rewardedAmount;
+
+ };
+
+ Array statsInfo;
+
struct getStateOfRound_locals {
uint32 firstEpoch;
};
@@ -258,6 +298,7 @@ struct QEARN : public ContractBase
struct getStatsPerEpoch_locals
{
+ ::Entity entity;
uint32 cnt, _t;
};
@@ -266,7 +307,9 @@ struct QEARN : public ContractBase
output.earlyUnlockedAmount = state._initialRoundInfo.get(input.epoch)._totalLockedAmount - state._currentRoundInfo.get(input.epoch)._totalLockedAmount;
output.earlyUnlockedPercent = QPI::div(output.earlyUnlockedAmount * 10000ULL, state._initialRoundInfo.get(input.epoch)._totalLockedAmount);
- output.totalLockedAmount = 0;
+ qpi.getEntity(SELF, locals.entity);
+ output.totalLockedAmount = locals.entity.incomingAmount - locals.entity.outgoingAmount;
+
output.averageAPY = 0;
locals.cnt = 0;
@@ -282,12 +325,54 @@ struct QEARN : public ContractBase
}
locals.cnt++;
- output.totalLockedAmount += state._currentRoundInfo.get(locals._t)._totalLockedAmount;
output.averageAPY += QPI::div(state._currentRoundInfo.get(locals._t)._epochBonusAmount * 10000000ULL, state._currentRoundInfo.get(locals._t)._totalLockedAmount);
}
output.averageAPY = QPI::div(output.averageAPY, locals.cnt * 1ULL);
+
+ _
+ struct getBurnedAndBoostedStats_locals
+ {
+ uint32 _t;
+ };
+
+ PUBLIC_FUNCTION_WITH_LOCALS(getBurnedAndBoostedStats)
+
+ output.boostedAmount = 0;
+ output.burnedAmount = 0;
+ output.rewardedAmount = 0;
+ output.averageBurnedPercent = 0;
+ output.averageBoostedPercent = 0;
+ output.averageRewardedPercent = 0;
+
+ for(locals._t = 138; locals._t < qpi.epoch(); locals._t++)
+ {
+ output.boostedAmount += state.statsInfo.get(locals._t).boostedAmount;
+ output.burnedAmount += state.statsInfo.get(locals._t).burnedAmount;
+ output.rewardedAmount += state.statsInfo.get(locals._t).rewardedAmount;
+
+ output.averageBurnedPercent += div(state.statsInfo.get(locals._t).burnedAmount * 10000000, state._initialRoundInfo.get(locals._t)._epochBonusAmount);
+ output.averageBoostedPercent += div(state.statsInfo.get(locals._t).boostedAmount * 10000000, state._initialRoundInfo.get(locals._t)._epochBonusAmount);
+ output.averageRewardedPercent += div(state.statsInfo.get(locals._t).rewardedAmount * 10000000, state._initialRoundInfo.get(locals._t)._epochBonusAmount);
+ }
+
+ output.averageBurnedPercent = div(output.averageBurnedPercent, qpi.epoch() - 138ULL);
+ output.averageBoostedPercent = div(output.averageBoostedPercent, qpi.epoch() - 138ULL);
+ output.averageRewardedPercent = div(output.averageRewardedPercent, qpi.epoch() - 138ULL);
+
+ _
+
+ PUBLIC_FUNCTION(getBurnedAndBoostedStatsPerEpoch)
+
+ output.boostedAmount = state.statsInfo.get(input.epoch).boostedAmount;
+ output.burnedAmount = state.statsInfo.get(input.epoch).burnedAmount;
+ output.rewardedAmount = state.statsInfo.get(input.epoch).rewardedAmount;
+
+ output.burnedPercent = div(state.statsInfo.get(input.epoch).burnedAmount * 10000000, state._initialRoundInfo.get(input.epoch)._epochBonusAmount);
+ output.boostedPercent = div(state.statsInfo.get(input.epoch).boostedAmount * 10000000, state._initialRoundInfo.get(input.epoch)._epochBonusAmount);
+ output.rewardedPercent = div(state.statsInfo.get(input.epoch).rewardedAmount * 10000000, state._initialRoundInfo.get(input.epoch)._epochBonusAmount);
+
_
struct getUserLockedInfo_locals {
@@ -478,6 +563,7 @@ struct QEARN : public ContractBase
RoundInfo updatedRoundInfo;
LockInfo updatedUserInfo;
HistoryInfo unlockerInfo;
+ StatsInfo tmpStats;
uint64 amountOfUnlocking;
uint64 amountOfReward;
@@ -640,6 +726,15 @@ struct QEARN : public ContractBase
qpi.transfer(qpi.invocator(), locals.amountOfUnlocking + locals.amountOfReward);
qpi.burn(locals.amountOfburn);
+ if(input.lockedEpoch != qpi.epoch())
+ {
+ locals.tmpStats.burnedAmount = state.statsInfo.get(input.lockedEpoch).burnedAmount + locals.amountOfburn;
+ locals.tmpStats.rewardedAmount = state.statsInfo.get(input.lockedEpoch).rewardedAmount + locals.amountOfReward;
+ locals.tmpStats.boostedAmount = state.statsInfo.get(input.lockedEpoch).boostedAmount + QPI::div(locals.divCalcu * (100 - locals.burnPercent - locals.earlyUnlockingPercent) * 1ULL, 10000000ULL);
+
+ state.statsInfo.set(input.lockedEpoch, locals.tmpStats);
+ }
+
locals.updatedRoundInfo._totalLockedAmount = state._currentRoundInfo.get(input.lockedEpoch)._totalLockedAmount - locals.amountOfUnlocking;
locals.updatedRoundInfo._epochBonusAmount = state._currentRoundInfo.get(input.lockedEpoch)._epochBonusAmount - locals.amountOfReward - locals.amountOfburn;
@@ -722,6 +817,8 @@ struct QEARN : public ContractBase
REGISTER_USER_FUNCTION(getUserLockStatus, 4);
REGISTER_USER_FUNCTION(getEndedStatus, 5);
REGISTER_USER_FUNCTION(getStatsPerEpoch, 6);
+ REGISTER_USER_FUNCTION(getBurnedAndBoostedStats, 7);
+ REGISTER_USER_FUNCTION(getBurnedAndBoostedStatsPerEpoch, 8);
REGISTER_USER_PROCEDURE(lock, 1);
REGISTER_USER_PROCEDURE(unlock, 2);
@@ -733,6 +830,7 @@ struct QEARN : public ContractBase
HistoryInfo INITIALIZE_HISTORY;
LockInfo INITIALIZE_USER;
RoundInfo INITIALIZE_ROUNDINFO;
+ StatsInfo INITIALIZE_STATS;
uint32 t;
bit status;
@@ -767,17 +865,6 @@ struct QEARN : public ContractBase
state._initialRoundInfo.set(qpi.epoch(), locals.INITIALIZE_ROUNDINFO);
state._currentRoundInfo.set(qpi.epoch(), locals.INITIALIZE_ROUNDINFO);
-
- /*
- the initial total locked amount should exclude the amount that locked on initial epoch but it didn't exclude that amount before.
- so now it is updated.
- I recorded the initial total locked amount of epoch 139 with 1834842583179.
- This updates should be deployed on mainnet to chnage the initial infos of epoch 139. it will be deleted an epoch after deployment on mainnet.
- */
- locals.INITIALIZE_ROUNDINFO._epochBonusAmount = state._initialRoundInfo.get(139)._epochBonusAmount;
- locals.INITIALIZE_ROUNDINFO._totalLockedAmount = 1834842583179;
-
- state._initialRoundInfo.set(139, locals.INITIALIZE_ROUNDINFO);
_
struct END_EPOCH_locals
@@ -786,6 +873,7 @@ struct QEARN : public ContractBase
LockInfo INITIALIZE_USER;
RoundInfo INITIALIZE_ROUNDINFO;
EpochIndexInfo tmpEpochIndex;
+ StatsInfo tmpStats;
uint64 _rewardPercent;
uint64 _rewardAmount;
@@ -809,6 +897,7 @@ struct QEARN : public ContractBase
locals._burnAmount = state._currentRoundInfo.get(locals.lockedEpoch)._epochBonusAmount;
locals._rewardPercent = QPI::div(state._currentRoundInfo.get(locals.lockedEpoch)._epochBonusAmount * 10000000ULL, state._currentRoundInfo.get(locals.lockedEpoch)._totalLockedAmount);
+ locals.tmpStats.rewardedAmount = state.statsInfo.get(locals.lockedEpoch).rewardedAmount;
for(locals._t = state._epochIndex.get(locals.lockedEpoch).startIndex; locals._t < locals.endIndex; locals._t++)
{
@@ -841,6 +930,7 @@ struct QEARN : public ContractBase
state.locker.set(locals._t, locals.INITIALIZE_USER);
locals._burnAmount -= locals._rewardAmount;
+ locals.tmpStats.rewardedAmount += locals._rewardAmount;
}
locals.tmpEpochIndex.startIndex = 0;
@@ -907,5 +997,10 @@ struct QEARN : public ContractBase
state._epochIndex.set(qpi.epoch() + 1, locals.tmpEpochIndex);
qpi.burn(locals._burnAmount);
+
+ locals.tmpStats.boostedAmount = state.statsInfo.get(locals.lockedEpoch).boostedAmount;
+ locals.tmpStats.burnedAmount = state.statsInfo.get(locals.lockedEpoch).burnedAmount + locals._burnAmount;
+
+ state.statsInfo.set(locals.lockedEpoch, locals.tmpStats);
_
};
diff --git a/src/contracts/Qearn_old.h b/src/contracts/Qearn_old.h
new file mode 100644
index 00000000..9e2ee051
--- /dev/null
+++ b/src/contracts/Qearn_old.h
@@ -0,0 +1,911 @@
+using namespace QPI;
+
+constexpr uint64 QEARN_MINIMUM_LOCKING_AMOUNT = 10000000;
+constexpr uint64 QEARN_MAX_LOCKS = 4194304;
+constexpr uint64 QEARN_MAX_EPOCHS = 4096;
+constexpr uint64 QEARN_MAX_USERS = 131072;
+constexpr uint64 QEARN_MAX_LOCK_AMOUNT = 1000000000000ULL;
+constexpr uint64 QEARN_MAX_BONUS_AMOUNT = 1000000000000ULL;
+constexpr uint64 QEARN_INITIAL_EPOCH = 138;
+
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_0_3 = 0;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_4_7 = 5;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_8_11 = 5;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_12_15 = 10;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_16_19 = 15;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_20_23 = 20;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_24_27 = 25;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_28_31 = 30;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_32_35 = 35;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_36_39 = 40;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_40_43 = 45;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_44_47 = 50;
+constexpr uint64 QEARN_EARLY_UNLOCKING_PERCENT_48_51 = 55;
+
+constexpr uint64 QEARN_BURN_PERCENT_0_3 = 0;
+constexpr uint64 QEARN_BURN_PERCENT_4_7 = 45;
+constexpr uint64 QEARN_BURN_PERCENT_8_11 = 45;
+constexpr uint64 QEARN_BURN_PERCENT_12_15 = 45;
+constexpr uint64 QEARN_BURN_PERCENT_16_19 = 40;
+constexpr uint64 QEARN_BURN_PERCENT_20_23 = 40;
+constexpr uint64 QEARN_BURN_PERCENT_24_27 = 35;
+constexpr uint64 QEARN_BURN_PERCENT_28_31 = 35;
+constexpr uint64 QEARN_BURN_PERCENT_32_35 = 35;
+constexpr uint64 QEARN_BURN_PERCENT_36_39 = 30;
+constexpr uint64 QEARN_BURN_PERCENT_40_43 = 30;
+constexpr uint64 QEARN_BURN_PERCENT_44_47 = 30;
+constexpr uint64 QEARN_BURN_PERCENT_48_51 = 25;
+
+constexpr sint32 QEARN_INVALID_INPUT_AMOUNT = 0;
+constexpr sint32 QEARN_LOCK_SUCCESS = 1;
+constexpr sint32 QEARN_INVALID_INPUT_LOCKED_EPOCH = 2;
+constexpr sint32 QEARN_INVALID_INPUT_UNLOCK_AMOUNT = 3;
+constexpr sint32 QEARN_EMPTY_LOCKED = 4;
+constexpr sint32 QEARN_UNLOCK_SUCCESS = 5;
+constexpr sint32 QEARN_OVERFLOW_USER = 6;
+constexpr sint32 QEARN_LIMIT_LOCK = 7;
+
+struct QEARN2
+{
+};
+
+struct QEARN : public ContractBase
+{
+public:
+ struct getLockInfoPerEpoch_input {
+ uint32 Epoch; /* epoch number to get information */
+ };
+
+ struct getLockInfoPerEpoch_output {
+ uint64 lockedAmount; /* initial total locked amount in epoch */
+ uint64 bonusAmount; /* initial bonus amount in epoch*/
+ uint64 currentLockedAmount; /* total locked amount in epoch. exactly the amount excluding the amount unlocked early*/
+ uint64 currentBonusAmount; /* bonus amount in epoch excluding the early unlocking */
+ uint64 yield; /* Yield calculated by 10000000 multiple*/
+ };
+
+ struct getUserLockedInfo_input {
+ id user;
+ uint32 epoch;
+ };
+
+ struct getUserLockedInfo_output {
+ uint64 lockedAmount; /* the amount user locked at input.epoch */
+ };
+
+ /*
+ getStateOfRound FUNCTION
+
+ getStateOfRound function returns following.
+
+ 0 = open epoch,not started yet
+ 1 = running epoch
+ 2 = ended epoch(>52weeks)
+ */
+ struct getStateOfRound_input {
+ uint32 epoch;
+ };
+
+ struct getStateOfRound_output {
+ uint32 state;
+ };
+
+ /*
+ getUserLockStatus FUNCTION
+
+ the status will return the binary status.
+ 1101010010110101001011010100101101010010110101001001
+
+ 1 means locked in [index of 1] weeks ago. 0 means unlocked in [index of zero] weeks ago.
+ The frontend can get the status of locked in 52 epochs. in above binary status,
+ the frontend can know that user locked 0 week ago, 1 week ago, 3 weeks ago, 5, 8,10,11,13 weeks ago.
+ */
+ struct getUserLockStatus_input {
+ id user;
+ };
+
+ struct getUserLockStatus_output {
+ uint64 status;
+ };
+
+ /*
+ getEndedStatus FUNCTION
+
+ output.earlyRewardedAmount returns the amount rewarded by unlocking early at current epoch
+ output.earlyUnlockedAmount returns the amount unlocked by unlocking early at current epoch
+ output.fullyRewardedAmount returns the amount rewarded by unlocking fully at the end of previous epoch
+ output.fullyUnlockedAmount returns the amount unlocked by unlocking fully at the end of previous epoch
+
+ let's assume that current epoch is 170, user unlocked the 15B qu totally at this epoch and he got the 30B qu of reward.
+ in this case, output.earlyUnlockedAmount = 15B qu, output.earlyRewardedAmount = 30B qu
+ if this user unlocks 3B qu additionally at this epoch and rewarded 6B qu,
+ in this case, output.earlyUnlockedAmount = 18B qu, output.earlyRewardedAmount = 36B qu
+ state.earlyUnlocker array would be initialized at the end of every epoch
+
+ let's assume also that current epoch is 170, user got the 15B(locked amount for 52 weeks) + 10B(rewarded amount for 52 weeks) at the end of epoch 169.
+ in this case, output.fullyRewardedAmount = 10B, output.fullyUnlockedAmount = 15B
+ state.fullyUnlocker array would be decided with distributions at the end of every epoch
+
+ state.earlyUnlocker, state.fullyUnlocker arrays would be initialized and decided by following expression at the END_EPOCH_WITH_LOCALS function.
+ state._earlyUnlockedCnt = 0;
+ state._fullyUnlockedCnt = 0;
+ */
+
+ struct getEndedStatus_input {
+ id user;
+ };
+
+ struct getEndedStatus_output {
+ uint64 fullyUnlockedAmount;
+ uint64 fullyRewardedAmount;
+ uint64 earlyUnlockedAmount;
+ uint64 earlyRewardedAmount;
+ };
+
+ struct lock_input {
+ };
+
+ struct lock_output {
+ sint32 returnCode;
+ };
+
+ struct unlock_input {
+ uint64 amount; /* unlocking amount */
+ uint32 lockedEpoch; /* locked epoch */
+ };
+
+ struct unlock_output {
+ sint32 returnCode;
+ };
+
+ struct getStatsPerEpoch_input {
+ uint32 epoch;
+ };
+
+ struct getStatsPerEpoch_output {
+
+ uint64 earlyUnlockedAmount;
+ uint64 earlyUnlockedPercent;
+ uint64 totalLockedAmount;
+ uint64 averageAPY;
+
+ };
+
+protected:
+
+ struct RoundInfo {
+
+ uint64 _totalLockedAmount; // The initial total locked amount in any epoch. Max Epoch is 65535
+ uint64 _epochBonusAmount; // The initial bonus amount per an epoch. Max Epoch is 65535
+
+ };
+
+ Array _initialRoundInfo;
+ Array _currentRoundInfo;
+
+ struct EpochIndexInfo {
+
+ uint32 startIndex;
+ uint32 endIndex;
+ };
+
+ Array _epochIndex;
+
+ struct LockInfo {
+
+ uint64 _lockedAmount;
+ id ID;
+ uint32 _lockedEpoch;
+
+ };
+
+ Array locker;
+
+ struct HistoryInfo {
+
+ uint64 _unlockedAmount;
+ uint64 _rewardedAmount;
+ id _unlockedID;
+
+ };
+
+ Array earlyUnlocker;
+ Array fullyUnlocker;
+
+ uint32 _earlyUnlockedCnt;
+ uint32 _fullyUnlockedCnt;
+
+ struct getStateOfRound_locals {
+ uint32 firstEpoch;
+ };
+
+ PUBLIC_FUNCTION_WITH_LOCALS(getStateOfRound)
+ if(input.epoch < QEARN_INITIAL_EPOCH)
+ { // non staking
+ output.state = 2;
+ return ;
+ }
+ if(input.epoch > qpi.epoch())
+ {
+ output.state = 0; // opening round, not started yet
+ }
+ locals.firstEpoch = qpi.epoch() - 52;
+ if(input.epoch <= qpi.epoch() && input.epoch >= locals.firstEpoch)
+ {
+ output.state = 1; // running round, available unlocking early
+ }
+ if(input.epoch < locals.firstEpoch)
+ {
+ output.state = 2; // ended round
+ }
+ _
+
+ PUBLIC_FUNCTION(getLockInfoPerEpoch)
+
+ output.bonusAmount = state._initialRoundInfo.get(input.Epoch)._epochBonusAmount;
+ output.lockedAmount = state._initialRoundInfo.get(input.Epoch)._totalLockedAmount;
+ output.currentBonusAmount = state._currentRoundInfo.get(input.Epoch)._epochBonusAmount;
+ output.currentLockedAmount = state._currentRoundInfo.get(input.Epoch)._totalLockedAmount;
+ if(state._currentRoundInfo.get(input.Epoch)._totalLockedAmount)
+ {
+ output.yield = state._currentRoundInfo.get(input.Epoch)._epochBonusAmount * 10000000ULL / state._currentRoundInfo.get(input.Epoch)._totalLockedAmount;
+ }
+ else
+ {
+ output.yield = 0ULL;
+ }
+ _
+
+ struct getStatsPerEpoch_locals
+ {
+ uint32 cnt, _t;
+ };
+
+ PUBLIC_FUNCTION_WITH_LOCALS(getStatsPerEpoch)
+
+ output.earlyUnlockedAmount = state._initialRoundInfo.get(input.epoch)._totalLockedAmount - state._currentRoundInfo.get(input.epoch)._totalLockedAmount;
+ output.earlyUnlockedPercent = QPI::div(output.earlyUnlockedAmount * 10000ULL, state._initialRoundInfo.get(input.epoch)._totalLockedAmount);
+
+ output.totalLockedAmount = 0;
+ output.averageAPY = 0;
+ locals.cnt = 0;
+
+ for(locals._t = qpi.epoch() - 1U; locals._t >= qpi.epoch() - 52U; locals._t--)
+ {
+ if(locals._t < QEARN_INITIAL_EPOCH)
+ {
+ break;
+ }
+ if(state._currentRoundInfo.get(locals._t)._totalLockedAmount == 0)
+ {
+ continue;
+ }
+
+ locals.cnt++;
+ output.totalLockedAmount += state._currentRoundInfo.get(locals._t)._totalLockedAmount;
+ output.averageAPY += QPI::div(state._currentRoundInfo.get(locals._t)._epochBonusAmount * 10000000ULL, state._currentRoundInfo.get(locals._t)._totalLockedAmount);
+ }
+
+ output.averageAPY = QPI::div(output.averageAPY, locals.cnt * 1ULL);
+
+ _
+
+ struct getUserLockedInfo_locals {
+ uint32 _t;
+ uint32 startIndex;
+ uint32 endIndex;
+ };
+
+ PUBLIC_FUNCTION_WITH_LOCALS(getUserLockedInfo)
+
+ locals.startIndex = state._epochIndex.get(input.epoch).startIndex;
+ locals.endIndex = state._epochIndex.get(input.epoch).endIndex;
+
+ for(locals._t = locals.startIndex; locals._t < locals.endIndex; locals._t++)
+ {
+ if(state.locker.get(locals._t).ID == input.user)
+ {
+ output.lockedAmount = state.locker.get(locals._t)._lockedAmount;
+ return;
+ }
+ }
+ _
+
+ struct getUserLockStatus_locals {
+ uint64 bn;
+ uint32 _t;
+ uint32 _r;
+ uint32 endIndex;
+ uint8 lockedWeeks;
+ };
+
+ PUBLIC_FUNCTION_WITH_LOCALS(getUserLockStatus)
+
+ output.status = 0ULL;
+ locals.endIndex = state._epochIndex.get(qpi.epoch()).endIndex;
+
+ for(locals._t = 0; locals._t < locals.endIndex; locals._t++)
+ {
+ if(state.locker.get(locals._t)._lockedAmount > 0 && state.locker.get(locals._t).ID == input.user)
+ {
+
+ locals.lockedWeeks = qpi.epoch() - state.locker.get(locals._t)._lockedEpoch;
+ locals.bn = 1ULL< 0)
+ {
+ qpi.transfer(qpi.invocator(), qpi.invocationReward());
+ }
+ return;
+ }
+
+ locals.endIndex = state._epochIndex.get(qpi.epoch()).endIndex;
+
+ for(locals.t = state._epochIndex.get(qpi.epoch()).startIndex ; locals.t < locals.endIndex; locals.t++)
+ {
+
+ if(state.locker.get(locals.t).ID == qpi.invocator())
+ { // the case to be locked several times at one epoch, at that time, this address already located in state.Locker array, the amount will be increased as current locking amount.
+ if(state.locker.get(locals.t)._lockedAmount + qpi.invocationReward() > QEARN_MAX_LOCK_AMOUNT)
+ {
+ output.returnCode = QEARN_LIMIT_LOCK;
+ if(qpi.invocationReward() > 0)
+ {
+ qpi.transfer(qpi.invocator(), qpi.invocationReward());
+ }
+ return;
+ }
+
+ locals.newLocker._lockedAmount = state.locker.get(locals.t)._lockedAmount + qpi.invocationReward();
+ locals.newLocker._lockedEpoch = qpi.epoch();
+ locals.newLocker.ID = qpi.invocator();
+
+ state.locker.set(locals.t, locals.newLocker);
+
+ locals.updatedRoundInfo._totalLockedAmount = state._initialRoundInfo.get(qpi.epoch())._totalLockedAmount + qpi.invocationReward();
+ locals.updatedRoundInfo._epochBonusAmount = state._initialRoundInfo.get(qpi.epoch())._epochBonusAmount;
+ state._initialRoundInfo.set(qpi.epoch(), locals.updatedRoundInfo);
+
+ locals.updatedRoundInfo._totalLockedAmount = state._currentRoundInfo.get(qpi.epoch())._totalLockedAmount + qpi.invocationReward();
+ locals.updatedRoundInfo._epochBonusAmount = state._currentRoundInfo.get(qpi.epoch())._epochBonusAmount;
+ state._currentRoundInfo.set(qpi.epoch(), locals.updatedRoundInfo);
+
+ output.returnCode = QEARN_LOCK_SUCCESS; // additional locking of this epoch is succeed
+ return ;
+ }
+
+ }
+
+ if(locals.endIndex == QEARN_MAX_LOCKS - 1)
+ {
+ output.returnCode = QEARN_OVERFLOW_USER;
+ if(qpi.invocationReward() > 0)
+ {
+ qpi.transfer(qpi.invocator(), qpi.invocationReward());
+ }
+ return ; // overflow users in Qearn
+ }
+
+ if(qpi.invocationReward() > QEARN_MAX_LOCK_AMOUNT)
+ {
+ output.returnCode = QEARN_LIMIT_LOCK;
+ if(qpi.invocationReward() > 0)
+ {
+ qpi.transfer(qpi.invocator(), qpi.invocationReward());
+ }
+ return;
+ }
+
+ locals.newLocker.ID = qpi.invocator();
+ locals.newLocker._lockedAmount = qpi.invocationReward();
+ locals.newLocker._lockedEpoch = qpi.epoch();
+
+ state.locker.set(locals.endIndex, locals.newLocker);
+
+ locals.tmpIndex.startIndex = state._epochIndex.get(qpi.epoch()).startIndex;
+ locals.tmpIndex.endIndex = locals.endIndex + 1;
+ state._epochIndex.set(qpi.epoch(), locals.tmpIndex);
+
+ locals.updatedRoundInfo._totalLockedAmount = state._initialRoundInfo.get(qpi.epoch())._totalLockedAmount + qpi.invocationReward();
+ locals.updatedRoundInfo._epochBonusAmount = state._initialRoundInfo.get(qpi.epoch())._epochBonusAmount;
+ state._initialRoundInfo.set(qpi.epoch(), locals.updatedRoundInfo);
+
+ locals.updatedRoundInfo._totalLockedAmount = state._currentRoundInfo.get(qpi.epoch())._totalLockedAmount + qpi.invocationReward();
+ locals.updatedRoundInfo._epochBonusAmount = state._currentRoundInfo.get(qpi.epoch())._epochBonusAmount;
+ state._currentRoundInfo.set(qpi.epoch(), locals.updatedRoundInfo);
+
+ output.returnCode = QEARN_LOCK_SUCCESS; // new locking of this epoch is succeed
+ _
+
+ struct unlock_locals {
+
+ RoundInfo updatedRoundInfo;
+ LockInfo updatedUserInfo;
+ HistoryInfo unlockerInfo;
+
+ uint64 amountOfUnlocking;
+ uint64 amountOfReward;
+ uint64 amountOfburn;
+ uint64 rewardPercent;
+ sint64 divCalcu;
+ uint32 earlyUnlockingPercent;
+ uint32 burnPercent;
+ uint32 indexOfinvocator;
+ uint32 _t;
+ uint32 countOfLastVacancy;
+ uint32 countOfLockedEpochs;
+ uint32 startIndex;
+ uint32 endIndex;
+
+ };
+
+ PUBLIC_PROCEDURE_WITH_LOCALS(unlock)
+
+ if (input.lockedEpoch > QEARN_MAX_EPOCHS || input.lockedEpoch < QEARN_INITIAL_EPOCH)
+ {
+
+ output.returnCode = QEARN_INVALID_INPUT_LOCKED_EPOCH; // if user try to unlock with wrong locked epoch, it should be failed to unlock.
+ return ;
+
+ }
+
+ if(input.amount < QEARN_MINIMUM_LOCKING_AMOUNT)
+ {
+
+ output.returnCode = QEARN_INVALID_INPUT_AMOUNT;
+ return ;
+
+ }
+
+ locals.indexOfinvocator = QEARN_MAX_LOCKS;
+ locals.startIndex = state._epochIndex.get(input.lockedEpoch).startIndex;
+ locals.endIndex = state._epochIndex.get(input.lockedEpoch).endIndex;
+
+ for(locals._t = locals.startIndex ; locals._t < locals.endIndex; locals._t++)
+ {
+
+ if(state.locker.get(locals._t).ID == qpi.invocator())
+ {
+ if(state.locker.get(locals._t)._lockedAmount < input.amount)
+ {
+
+ output.returnCode = QEARN_INVALID_INPUT_UNLOCK_AMOUNT; // if the amount to be wanted to unlock is more than locked amount, it should be failed to unlock
+ return ;
+
+ }
+ else
+ {
+ locals.indexOfinvocator = locals._t;
+ break;
+ }
+ }
+
+ }
+
+ if(locals.indexOfinvocator == QEARN_MAX_LOCKS)
+ {
+
+ output.returnCode = QEARN_EMPTY_LOCKED; // if there is no any locked info in state.Locker array, it shows this address didn't lock at the epoch (input.Locked_Epoch)
+ return ;
+ }
+
+ /* the rest amount after unlocking should be more than MINIMUM_LOCKING_AMOUNT */
+ if(state.locker.get(locals.indexOfinvocator)._lockedAmount - input.amount < QEARN_MINIMUM_LOCKING_AMOUNT)
+ {
+ locals.amountOfUnlocking = state.locker.get(locals.indexOfinvocator)._lockedAmount;
+ }
+ else
+ {
+ locals.amountOfUnlocking = input.amount;
+ }
+
+ locals.countOfLockedEpochs = qpi.epoch() - input.lockedEpoch - 1;
+
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_0_3;
+ locals.burnPercent = QEARN_BURN_PERCENT_0_3;
+
+ if(locals.countOfLockedEpochs >= 4 && locals.countOfLockedEpochs <= 7)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_4_7;
+ locals.burnPercent = QEARN_BURN_PERCENT_4_7;
+ }
+
+ else if(locals.countOfLockedEpochs >= 8 && locals.countOfLockedEpochs <= 11)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_8_11;
+ locals.burnPercent = QEARN_BURN_PERCENT_8_11;
+ }
+
+ else if(locals.countOfLockedEpochs >= 12 && locals.countOfLockedEpochs <= 15)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_12_15;
+ locals.burnPercent = QEARN_BURN_PERCENT_12_15;
+ }
+
+ else if(locals.countOfLockedEpochs >= 16 && locals.countOfLockedEpochs <= 19)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_16_19;
+ locals.burnPercent = QEARN_BURN_PERCENT_16_19;
+ }
+
+ else if(locals.countOfLockedEpochs >= 20 && locals.countOfLockedEpochs <= 23)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_20_23;
+ locals.burnPercent = QEARN_BURN_PERCENT_20_23;
+ }
+
+ else if(locals.countOfLockedEpochs >= 24 && locals.countOfLockedEpochs <= 27)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_24_27;
+ locals.burnPercent = QEARN_BURN_PERCENT_24_27;
+ }
+
+ else if(locals.countOfLockedEpochs >= 28 && locals.countOfLockedEpochs <= 31)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_28_31;
+ locals.burnPercent = QEARN_BURN_PERCENT_28_31;
+ }
+
+ else if(locals.countOfLockedEpochs >= 32 && locals.countOfLockedEpochs <= 35)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_32_35;
+ locals.burnPercent = QEARN_BURN_PERCENT_32_35;
+ }
+
+ else if(locals.countOfLockedEpochs >= 36 && locals.countOfLockedEpochs <= 39)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_36_39;
+ locals.burnPercent = QEARN_BURN_PERCENT_36_39;
+ }
+
+ else if(locals.countOfLockedEpochs >= 40 && locals.countOfLockedEpochs <= 43)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_40_43;
+ locals.burnPercent = QEARN_BURN_PERCENT_40_43;
+ }
+
+ else if(locals.countOfLockedEpochs >= 44 && locals.countOfLockedEpochs <= 47)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_44_47;
+ locals.burnPercent = QEARN_BURN_PERCENT_44_47;
+ }
+
+ else if(locals.countOfLockedEpochs >= 48 && locals.countOfLockedEpochs <= 51)
+ {
+ locals.earlyUnlockingPercent = QEARN_EARLY_UNLOCKING_PERCENT_48_51;
+ locals.burnPercent = QEARN_BURN_PERCENT_48_51;
+ }
+
+ locals.rewardPercent = QPI::div(state._currentRoundInfo.get(input.lockedEpoch)._epochBonusAmount * 10000000ULL, state._currentRoundInfo.get(input.lockedEpoch)._totalLockedAmount);
+ locals.divCalcu = QPI::div(locals.rewardPercent * locals.amountOfUnlocking , 100ULL);
+ locals.amountOfReward = QPI::div(locals.divCalcu * locals.earlyUnlockingPercent * 1ULL , 10000000ULL);
+ locals.amountOfburn = QPI::div(locals.divCalcu * locals.burnPercent * 1ULL, 10000000ULL);
+
+ qpi.transfer(qpi.invocator(), locals.amountOfUnlocking + locals.amountOfReward);
+ qpi.burn(locals.amountOfburn);
+
+ locals.updatedRoundInfo._totalLockedAmount = state._currentRoundInfo.get(input.lockedEpoch)._totalLockedAmount - locals.amountOfUnlocking;
+ locals.updatedRoundInfo._epochBonusAmount = state._currentRoundInfo.get(input.lockedEpoch)._epochBonusAmount - locals.amountOfReward - locals.amountOfburn;
+
+ state._currentRoundInfo.set(input.lockedEpoch, locals.updatedRoundInfo);
+
+ if(qpi.epoch() == input.lockedEpoch)
+ {
+ locals.updatedRoundInfo._totalLockedAmount = state._initialRoundInfo.get(input.lockedEpoch)._totalLockedAmount - locals.amountOfUnlocking;
+ locals.updatedRoundInfo._epochBonusAmount = state._initialRoundInfo.get(input.lockedEpoch)._epochBonusAmount;
+
+ state._initialRoundInfo.set(input.lockedEpoch, locals.updatedRoundInfo);
+ }
+
+ if(state.locker.get(locals.indexOfinvocator)._lockedAmount == locals.amountOfUnlocking)
+ {
+ locals.updatedUserInfo.ID = NULL_ID;
+ locals.updatedUserInfo._lockedAmount = 0;
+ locals.updatedUserInfo._lockedEpoch = 0;
+ }
+ else
+ {
+ locals.updatedUserInfo.ID = qpi.invocator();
+ locals.updatedUserInfo._lockedAmount = state.locker.get(locals.indexOfinvocator)._lockedAmount - locals.amountOfUnlocking;
+ locals.updatedUserInfo._lockedEpoch = state.locker.get(locals.indexOfinvocator)._lockedEpoch;
+ }
+
+ state.locker.set(locals.indexOfinvocator, locals.updatedUserInfo);
+
+ if(state._currentRoundInfo.get(input.lockedEpoch)._totalLockedAmount == 0 && input.lockedEpoch != qpi.epoch())
+ {
+
+ // If all users have unlocked early, burn bonus
+ qpi.burn(state._currentRoundInfo.get(input.lockedEpoch)._epochBonusAmount);
+
+ locals.updatedRoundInfo._totalLockedAmount = 0;
+ locals.updatedRoundInfo._epochBonusAmount = 0;
+
+ state._currentRoundInfo.set(input.lockedEpoch, locals.updatedRoundInfo);
+
+ }
+
+ if(input.lockedEpoch != qpi.epoch())
+ {
+
+ locals.unlockerInfo._unlockedID = qpi.invocator();
+
+ for(locals._t = 0; locals._t < state._earlyUnlockedCnt; locals._t++)
+ {
+ if(state.earlyUnlocker.get(locals._t)._unlockedID == qpi.invocator())
+ {
+
+ locals.unlockerInfo._rewardedAmount = state.earlyUnlocker.get(locals._t)._rewardedAmount + locals.amountOfReward;
+ locals.unlockerInfo._unlockedAmount = state.earlyUnlocker.get(locals._t)._unlockedAmount + locals.amountOfUnlocking;
+
+ state.earlyUnlocker.set(locals._t, locals.unlockerInfo);
+
+ break;
+ }
+ }
+
+ if(locals._t == state._earlyUnlockedCnt && state._earlyUnlockedCnt < QEARN_MAX_USERS)
+ {
+ locals.unlockerInfo._rewardedAmount = locals.amountOfReward;
+ locals.unlockerInfo._unlockedAmount = locals.amountOfUnlocking;
+
+ state.earlyUnlocker.set(locals._t, locals.unlockerInfo);
+ state._earlyUnlockedCnt++;
+ }
+
+ }
+
+ output.returnCode = QEARN_UNLOCK_SUCCESS; // unlock is succeed
+ _
+
+ REGISTER_USER_FUNCTIONS_AND_PROCEDURES
+
+ REGISTER_USER_FUNCTION(getLockInfoPerEpoch, 1);
+ REGISTER_USER_FUNCTION(getUserLockedInfo, 2);
+ REGISTER_USER_FUNCTION(getStateOfRound, 3);
+ REGISTER_USER_FUNCTION(getUserLockStatus, 4);
+ REGISTER_USER_FUNCTION(getEndedStatus, 5);
+ REGISTER_USER_FUNCTION(getStatsPerEpoch, 6);
+
+ REGISTER_USER_PROCEDURE(lock, 1);
+ REGISTER_USER_PROCEDURE(unlock, 2);
+
+ _
+
+ struct BEGIN_EPOCH_locals
+ {
+ HistoryInfo INITIALIZE_HISTORY;
+ LockInfo INITIALIZE_USER;
+ RoundInfo INITIALIZE_ROUNDINFO;
+
+ uint32 t;
+ bit status;
+ uint64 pre_epoch_balance;
+ uint64 current_balance;
+ ::Entity entity;
+ uint32 locked_epoch;
+ };
+
+ BEGIN_EPOCH_WITH_LOCALS
+
+ qpi.getEntity(SELF, locals.entity);
+ locals.current_balance = locals.entity.incomingAmount - locals.entity.outgoingAmount;
+
+ locals.pre_epoch_balance = 0ULL;
+ locals.locked_epoch = qpi.epoch() - 52;
+ for(locals.t = qpi.epoch() - 1; locals.t >= locals.locked_epoch; locals.t--)
+ {
+ locals.pre_epoch_balance += state._currentRoundInfo.get(locals.t)._epochBonusAmount + state._currentRoundInfo.get(locals.t)._totalLockedAmount;
+ }
+
+ if(locals.current_balance - locals.pre_epoch_balance > QEARN_MAX_BONUS_AMOUNT)
+ {
+ qpi.burn(locals.current_balance - locals.pre_epoch_balance - QEARN_MAX_BONUS_AMOUNT);
+ locals.INITIALIZE_ROUNDINFO._epochBonusAmount = QEARN_MAX_BONUS_AMOUNT;
+ }
+ else
+ {
+ locals.INITIALIZE_ROUNDINFO._epochBonusAmount = locals.current_balance - locals.pre_epoch_balance;
+ }
+ locals.INITIALIZE_ROUNDINFO._totalLockedAmount = 0;
+
+ state._initialRoundInfo.set(qpi.epoch(), locals.INITIALIZE_ROUNDINFO);
+ state._currentRoundInfo.set(qpi.epoch(), locals.INITIALIZE_ROUNDINFO);
+
+ /*
+ the initial total locked amount should exclude the amount that locked on initial epoch but it didn't exclude that amount before.
+ so now it is updated.
+ I recorded the initial total locked amount of epoch 139 with 1834842583179.
+ This updates should be deployed on mainnet to chnage the initial infos of epoch 139. it will be deleted an epoch after deployment on mainnet.
+ */
+ locals.INITIALIZE_ROUNDINFO._epochBonusAmount = state._initialRoundInfo.get(139)._epochBonusAmount;
+ locals.INITIALIZE_ROUNDINFO._totalLockedAmount = 1834842583179;
+
+ state._initialRoundInfo.set(139, locals.INITIALIZE_ROUNDINFO);
+ _
+
+ struct END_EPOCH_locals
+ {
+ HistoryInfo INITIALIZE_HISTORY;
+ LockInfo INITIALIZE_USER;
+ RoundInfo INITIALIZE_ROUNDINFO;
+ EpochIndexInfo tmpEpochIndex;
+
+ uint64 _rewardPercent;
+ uint64 _rewardAmount;
+ uint64 _burnAmount;
+ uint32 lockedEpoch;
+ uint32 startEpoch;
+ uint32 _t;
+ sint32 st;
+ sint32 en;
+ uint32 endIndex;
+
+ };
+
+ END_EPOCH_WITH_LOCALS
+
+ state._earlyUnlockedCnt = 0;
+ state._fullyUnlockedCnt = 0;
+ locals.lockedEpoch = qpi.epoch() - 52;
+ locals.endIndex = state._epochIndex.get(locals.lockedEpoch).endIndex;
+
+ locals._burnAmount = state._currentRoundInfo.get(locals.lockedEpoch)._epochBonusAmount;
+
+ locals._rewardPercent = QPI::div(state._currentRoundInfo.get(locals.lockedEpoch)._epochBonusAmount * 10000000ULL, state._currentRoundInfo.get(locals.lockedEpoch)._totalLockedAmount);
+
+ for(locals._t = state._epochIndex.get(locals.lockedEpoch).startIndex; locals._t < locals.endIndex; locals._t++)
+ {
+ if(state.locker.get(locals._t)._lockedAmount == 0)
+ {
+ continue;
+ }
+
+ ASSERT(state.locker.get(locals._t)._lockedEpoch == locals.lockedEpoch);
+
+ locals._rewardAmount = QPI::div(state.locker.get(locals._t)._lockedAmount * locals._rewardPercent, 10000000ULL);
+ qpi.transfer(state.locker.get(locals._t).ID, locals._rewardAmount + state.locker.get(locals._t)._lockedAmount);
+
+ if(state._fullyUnlockedCnt < QEARN_MAX_USERS)
+ {
+
+ locals.INITIALIZE_HISTORY._unlockedID = state.locker.get(locals._t).ID;
+ locals.INITIALIZE_HISTORY._unlockedAmount = state.locker.get(locals._t)._lockedAmount;
+ locals.INITIALIZE_HISTORY._rewardedAmount = locals._rewardAmount;
+
+ state.fullyUnlocker.set(state._fullyUnlockedCnt, locals.INITIALIZE_HISTORY);
+
+ state._fullyUnlockedCnt++;
+ }
+
+ locals.INITIALIZE_USER.ID = NULL_ID;
+ locals.INITIALIZE_USER._lockedAmount = 0;
+ locals.INITIALIZE_USER._lockedEpoch = 0;
+
+ state.locker.set(locals._t, locals.INITIALIZE_USER);
+
+ locals._burnAmount -= locals._rewardAmount;
+ }
+
+ locals.tmpEpochIndex.startIndex = 0;
+ locals.tmpEpochIndex.endIndex = 0;
+ state._epochIndex.set(locals.lockedEpoch, locals.tmpEpochIndex);
+
+ locals.startEpoch = locals.lockedEpoch + 1;
+ if (locals.startEpoch < QEARN_INITIAL_EPOCH)
+ locals.startEpoch = QEARN_INITIAL_EPOCH;
+
+ // remove all gaps in Locker array (from beginning) and update epochIndex
+ locals.tmpEpochIndex.startIndex = 0;
+ for(locals._t = locals.startEpoch; locals._t <= qpi.epoch(); locals._t++)
+ {
+ // This for loop iteration moves all elements of one epoch the to start of its range of the Locker array.
+ // The startIndex is given by the end of the range of the previous epoch, the new endIndex is found in the
+ // gap removal process.
+ locals.st = locals.tmpEpochIndex.startIndex;
+ locals.en = state._epochIndex.get(locals._t).endIndex;
+ ASSERT(locals.st <= locals.en);
+
+ while(locals.st < locals.en)
+ {
+ // try to set locals.st to first empty slot
+ while (state.locker.get(locals.st)._lockedAmount && locals.st < locals.en)
+ {
+ locals.st++;
+ }
+
+ // try set locals.en to last non-empty slot in epoch
+ --locals.en;
+ while (!state.locker.get(locals.en)._lockedAmount && locals.st < locals.en)
+ {
+ locals.en--;
+ }
+
+ // if st and en meet, there are no gaps to be closed by moving in this epoch range
+ if (locals.st >= locals.en)
+ {
+ // make locals.en point behind last element again
+ ++locals.en;
+ break;
+ }
+
+ // move entry from locals.en to locals.st
+ state.locker.set(locals.st, state.locker.get(locals.en));
+
+ // make locals.en slot empty -> locals.en points behind last element again
+ locals.INITIALIZE_USER.ID = NULL_ID;
+ locals.INITIALIZE_USER._lockedAmount = 0;
+ locals.INITIALIZE_USER._lockedEpoch = 0;
+ state.locker.set(locals.en, locals.INITIALIZE_USER);
+ }
+
+ // update epoch index
+ locals.tmpEpochIndex.endIndex = locals.en;
+ state._epochIndex.set(locals._t, locals.tmpEpochIndex);
+
+ // set start index of next epoch to end index of current epoch
+ locals.tmpEpochIndex.startIndex = locals.tmpEpochIndex.endIndex;
+ }
+
+ locals.tmpEpochIndex.endIndex = locals.tmpEpochIndex.startIndex;
+ state._epochIndex.set(qpi.epoch() + 1, locals.tmpEpochIndex);
+
+ qpi.burn(locals._burnAmount);
+ _
+};
diff --git a/src/contracts/Quottery.h b/src/contracts/Quottery.h
index 093535e6..e988f44f 100644
--- a/src/contracts/Quottery.h
+++ b/src/contracts/Quottery.h
@@ -135,7 +135,7 @@ struct QUOTTERY : public ContractBase
};
struct getBetOptionDetail_output
{
- array bettor;
+ Array bettor;
};
struct getActiveBet_input
{
@@ -143,7 +143,7 @@ struct QUOTTERY : public ContractBase
struct getActiveBet_output
{
uint32 count;
- array activeBetId;
+ Array activeBetId;
};
struct getBetByCreator_input
{
@@ -152,7 +152,7 @@ struct QUOTTERY : public ContractBase
struct getBetByCreator_output
{
uint32 count;
- array betId;
+ Array betId;
};
struct cancelBet_input
{
@@ -201,27 +201,27 @@ struct QUOTTERY : public ContractBase
/**************************************/
/************CONTRACT STATES***********/
/**************************************/
- array mBetID;
- array mCreator;
- array mBetDesc;
- array mOptionDesc;
- array mBetAmountPerSlot;
- array mMaxNumberOfBetSlotPerOption;
- array mOracleProvider;
- array mOracleFees;
- array mCurrentBetState;
- array mNumberOption;
- array mOpenDate;
- array mCloseDate;
- array mEndDate;
- array mIsOccupied;
- array mBetEndTick;
+ Array mBetID;
+ Array mCreator;
+ Array mBetDesc;
+ Array mOptionDesc;
+ Array mBetAmountPerSlot;
+ Array mMaxNumberOfBetSlotPerOption;
+ Array mOracleProvider;
+ Array mOracleFees;
+ Array mCurrentBetState;
+ Array mNumberOption;
+ Array mOpenDate;
+ Array mCloseDate;
+ Array mEndDate;
+ Array mIsOccupied;
+ Array mBetEndTick;
//bettor info:
- array mBettorID;
- array mBettorBetOption;
+ Array mBettorID;
+ Array mBettorBetOption;
// bet result:
- array mBetResultWonOption;
- array mBetResultOPId;
+ Array mBetResultWonOption;
+ Array mBetResultOPId;
//static assert for developing:
static_assert(sizeof(mBetID) == (sizeof(uint32) * QUOTTERY_MAX_BET), "bet id array");
diff --git a/src/contracts/Qx.h b/src/contracts/Qx.h
index 3ee33a2a..c423a4f6 100644
--- a/src/contracts/Qx.h
+++ b/src/contracts/Qx.h
@@ -32,7 +32,7 @@ struct QX : public ContractBase
sint64 numberOfShares;
};
- array orders;
+ Array orders;
};
struct AssetBidOrders_input
@@ -50,7 +50,7 @@ struct QX : public ContractBase
sint64 numberOfShares;
};
- array orders;
+ Array orders;
};
struct EntityAskOrders_input
@@ -68,7 +68,7 @@ struct QX : public ContractBase
sint64 numberOfShares;
};
- array orders;
+ Array orders;
};
struct EntityBidOrders_input
@@ -86,7 +86,7 @@ struct QX : public ContractBase
sint64 numberOfShares;
};
- array orders;
+ Array orders;
};
struct IssueAsset_input
@@ -175,7 +175,7 @@ struct QX : public ContractBase
id entity;
sint64 numberOfShares;
};
- collection<_AssetOrder, 2097152 * X_MULTIPLIER> _assetOrders;
+ Collection<_AssetOrder, 2097152 * X_MULTIPLIER> _assetOrders;
struct _EntityOrder
{
@@ -183,7 +183,7 @@ struct QX : public ContractBase
uint64 assetName;
sint64 numberOfShares;
};
- collection<_EntityOrder, 2097152 * X_MULTIPLIER> _entityOrders;
+ Collection<_EntityOrder, 2097152 * X_MULTIPLIER> _entityOrders;
// TODO: change to "locals" variables and remove from state? -> every func/proc can define struct of "locals" that is passed as an argument (stored on stack structure per processor)
sint64 _elementIndex, _elementIndex2;
diff --git a/src/contracts/qpi.h b/src/contracts/qpi.h
index c12b900b..4a980a41 100644
--- a/src/contracts/qpi.h
+++ b/src/contracts/qpi.h
@@ -116,11 +116,11 @@ namespace QPI
// Array of L bits encoded in array of uint64 (overall size is at least 8 bytes, L must be 2^N)
template
- struct bit_array
+ struct BitArray
{
private:
static_assert(L && !(L & (L - 1)),
- "The capacity of the bit_array must be 2^N."
+ "The capacity of the BitArray must be 2^N."
);
static constexpr uint64 _bits = L;
@@ -175,23 +175,23 @@ namespace QPI
};
// Bit array convenience definitions
- typedef bit_array<2> bit_2;
- typedef bit_array<4> bit_4;
- typedef bit_array<8> bit_8;
- typedef bit_array<16> bit_16;
- typedef bit_array<32> bit_32;
- typedef bit_array<64> bit_64;
- typedef bit_array<128> bit_128;
- typedef bit_array<256> bit_256;
- typedef bit_array<512> bit_512;
- typedef bit_array<1024> bit_1024;
- typedef bit_array<2048> bit_2048;
- typedef bit_array<4096> bit_4096;
+ typedef BitArray<2> bit_2;
+ typedef BitArray<4> bit_4;
+ typedef BitArray<8> bit_8;
+ typedef BitArray<16> bit_16;
+ typedef BitArray<32> bit_32;
+ typedef BitArray<64> bit_64;
+ typedef BitArray<128> bit_128;
+ typedef BitArray<256> bit_256;
+ typedef BitArray<512> bit_512;
+ typedef BitArray<1024> bit_1024;
+ typedef BitArray<2048> bit_2048;
+ typedef BitArray<4096> bit_4096;
// Array of L elements of type T (L must be 2^N)
template
- struct array
+ struct Array
{
private:
static_assert(L && !(L & (L - 1)),
@@ -266,49 +266,49 @@ namespace QPI
};
// Array convenience definitions
- typedef array sint8_2;
- typedef array sint8_4;
- typedef array sint8_8;
+ typedef Array sint8_2;
+ typedef Array sint8_4;
+ typedef Array sint8_8;
- typedef array uint8_2;
- typedef array uint8_4;
- typedef array uint8_8;
+ typedef Array uint8_2;
+ typedef Array uint8_4;
+ typedef Array uint8_8;
- typedef array sint16_2;
- typedef array sint16_4;
- typedef array sint16_8;
+ typedef Array sint16_2;
+ typedef Array sint16_4;
+ typedef Array sint16_8;
- typedef array uint16_2;
- typedef array uint16_4;
- typedef array uint16_8;
+ typedef Array uint16_2;
+ typedef Array uint16_4;
+ typedef Array uint16_8;
- typedef array sint32_2;
- typedef array sint32_4;
- typedef array sint32_8;
+ typedef Array sint32_2;
+ typedef Array sint32_4;
+ typedef Array sint32_8;
- typedef array uint32_2;
- typedef array uint32_4;
- typedef array uint32_8;
+ typedef Array uint32_2;
+ typedef Array uint32_4;
+ typedef Array uint32_8;
- typedef array sint64_2;
- typedef array sint64_4;
- typedef array sint64_8;
+ typedef Array sint64_2;
+ typedef Array sint64_4;
+ typedef Array sint64_8;
- typedef array uint64_2;
- typedef array uint64_4;
- typedef array uint64_8;
+ typedef Array uint64_2;
+ typedef Array uint64_4;
+ typedef Array uint64_8;
- typedef array id_2;
- typedef array id_4;
- typedef array id_8;
+ typedef Array id_2;
+ typedef Array id_4;
+ typedef Array id_8;
// Check if array is sorted in given range (duplicates allowed). Returns false if range is invalid.
template
- bool isArraySorted(const array& array, uint64 beginIdx = 0, uint64 endIdx = L);
+ bool isArraySorted(const Array& Array, uint64 beginIdx = 0, uint64 endIdx = L);
// Check if array is sorted without duplicates in given range. Returns false if range is invalid.
template
- bool isArraySortedWithoutDuplicates(const array& array, uint64 beginIdx = 0, uint64 endIdx = L);
+ bool isArraySortedWithoutDuplicates(const Array