Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,3 @@ x64/
.DS_Store
.clang-format
tmp

# Build directories and temporary files
out/build/
**/Testing/Temporary/
**/_deps/googletest-src
2 changes: 1 addition & 1 deletion src/Qubic.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<ClInclude Include="assets\net_msg_impl.h" />
<ClInclude Include="common_buffers.h" />
<ClInclude Include="contracts\ComputorControlledFund.h" />
<ClInclude Include="contracts\Qdraw.h" />
<ClInclude Include="contracts\Qswap.h" />
<ClInclude Include="contracts\SupplyWatcher.h" />
<ClInclude Include="contracts\EmptyTemplate.h" />
Expand All @@ -39,7 +40,6 @@
<ClInclude Include="contracts\QVAULT.h" />
<ClInclude Include="contracts\QBAY.h" />
<ClInclude Include="contracts\Nostromo.h" />
<ClInclude Include="contracts\VottunBridge.h" />
<ClInclude Include="contracts\TestExampleA.h" />
<ClInclude Include="contracts\TestExampleB.h" />
<ClInclude Include="contracts\TestExampleC.h" />
Expand Down
2 changes: 1 addition & 1 deletion src/Qubic.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@
<ClInclude Include="contract_core\qpi_mining_impl.h">
<Filter>contract_core</Filter>
</ClInclude>
<ClInclude Include="contracts\VottunBridge.h">
<ClInclude Include="contracts\Qdraw.h">
<Filter>contracts</Filter>
</ClInclude>
</ItemGroup>
Expand Down
20 changes: 10 additions & 10 deletions src/contract_core/contract_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,17 +204,17 @@ struct __FunctionOrProcedureBeginEndGuard
#define CONTRACT_STATE2_TYPE NOST2
#include "contracts/Nostromo.h"

#ifndef NO_VBRIDGE
#ifndef NO_QDRAW

#undef CONTRACT_INDEX
#undef CONTRACT_STATE_TYPE
#undef CONTRACT_STATE2_TYPE

#define VOTTUNBRIDGE_CONTRACT_INDEX 15
#define CONTRACT_INDEX VOTTUNBRIDGE_CONTRACT_INDEX
#define CONTRACT_STATE_TYPE VOTTUNBRIDGE
#define CONTRACT_STATE2_TYPE VOTTUNBRIDGE2
#include "contracts/VottunBridge.h"
#define QDRAW_CONTRACT_INDEX 15
#define CONTRACT_INDEX QDRAW_CONTRACT_INDEX
#define CONTRACT_STATE_TYPE QDRAW
#define CONTRACT_STATE2_TYPE QDRAW2
#include "contracts/Qdraw.h"

#endif

Expand Down Expand Up @@ -315,8 +315,8 @@ constexpr struct ContractDescription
{"QBAY", 154, 10000, sizeof(QBAY)}, // proposal in epoch 152, IPO in 153, construction and first use in 154
{"QSWAP", 171, 10000, sizeof(QSWAP)}, // proposal in epoch 169, IPO in 170, construction and first use in 171
{"NOST", 172, 10000, sizeof(NOST)}, // proposal in epoch 170, IPO in 171, construction and first use in 172
#ifndef NO_VBRIDGE
{"VBRIDGE", 178, 10000, sizeof(VOTTUNBRIDGE)}, // proposal in epoch 176, IPO in 177, construction and first use in 178
#ifndef NO_QDRAW
{"QDRAW", 179, 10000, sizeof(QDRAW)}, // proposal in epoch 177, IPO in 178, construction and first use in 179
#endif
// new contracts should be added above this line
#ifdef INCLUDE_CONTRACT_TEST_EXAMPLES
Expand Down Expand Up @@ -421,8 +421,8 @@ static void initializeContracts()
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QBAY);
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QSWAP);
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(NOST);
#ifndef NO_VBRIDGE
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(VOTTUNBRIDGE);
#ifndef NO_QDRAW
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QDRAW);
#endif
// new contracts should be added above this line
#ifdef INCLUDE_CONTRACT_TEST_EXAMPLES
Expand Down
216 changes: 216 additions & 0 deletions src/contracts/Qdraw.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
using namespace QPI;

constexpr sint64 QDRAW_TICKET_PRICE = 1000000LL;
constexpr uint64 QDRAW_MAX_PARTICIPANTS = 1024 * X_MULTIPLIER;

struct QDRAW2
{
};

struct QDRAW : public ContractBase
{
public:
struct buyTicket_input
{
uint64 ticketCount;
};
struct buyTicket_output
{
};

struct getInfo_input
{
};
struct getInfo_output
{
sint64 pot;
uint64 participantCount;
id lastWinner;
sint64 lastWinAmount;
uint8 lastDrawHour;
uint8 currentHour;
uint8 nextDrawHour;
};


struct getParticipants_input
{
};
struct getParticipants_output
{
uint64 participantCount;
uint64 uniqueParticipantCount;
Array<id, QDRAW_MAX_PARTICIPANTS> participants;
Array<uint64, QDRAW_MAX_PARTICIPANTS> ticketCounts;
};

protected:
Array<id, QDRAW_MAX_PARTICIPANTS> _participants;
uint64 _participantCount;
sint64 _pot;
uint8 _lastDrawHour;
id _lastWinner;
sint64 _lastWinAmount;
id _owner;

struct buyTicket_locals
{
uint64 available;
sint64 totalCost;
uint64 i;
};

struct getParticipants_locals
{
uint64 uniqueCount;
uint64 i;
uint64 j;
bool found;
id p;
};

struct BEGIN_TICK_locals
{
uint8 currentHour;
id only;
id rand;
id winner;
uint64 loopIndex;
};

inline static bool isMonopoly(const Array<id, QDRAW_MAX_PARTICIPANTS>& arr, uint64 count, uint64 loopIndex)
{
if (count != QDRAW_MAX_PARTICIPANTS)
{
return false;
}
for (loopIndex = 1; loopIndex < count; ++loopIndex)
{
if (arr.get(loopIndex) != arr.get(0))
{
return false;
}
}
return true;
}

PUBLIC_PROCEDURE_WITH_LOCALS(buyTicket)
{
locals.available = QDRAW_MAX_PARTICIPANTS - state._participantCount;
if (QDRAW_MAX_PARTICIPANTS == state._participantCount || input.ticketCount == 0 || input.ticketCount > locals.available)
{
if (qpi.invocationReward() > 0)
{
qpi.transfer(qpi.invocator(), qpi.invocationReward());
}
return;
}
locals.totalCost = (sint64)input.ticketCount * (sint64)QDRAW_TICKET_PRICE;
if (qpi.invocationReward() < locals.totalCost)
{
if (qpi.invocationReward() > 0)
{
qpi.transfer(qpi.invocator(), qpi.invocationReward());
}
return;
}
for (locals.i = 0; locals.i < input.ticketCount; ++locals.i)
{
state._participants.set(state._participantCount + locals.i, qpi.invocator());
}
state._participantCount += input.ticketCount;
state._pot += locals.totalCost;
if (qpi.invocationReward() > locals.totalCost)
{
qpi.transfer(qpi.invocator(), qpi.invocationReward() - locals.totalCost);
}
}

PUBLIC_FUNCTION(getInfo)
{
output.pot = state._pot;
output.participantCount = state._participantCount;
output.lastDrawHour = state._lastDrawHour;
output.currentHour = qpi.hour();
output.nextDrawHour = (uint8)(mod(qpi.hour() + 1, 24));
output.lastWinner = state._lastWinner;
output.lastWinAmount = state._lastWinAmount;
}

PUBLIC_FUNCTION_WITH_LOCALS(getParticipants)
{
locals.uniqueCount = 0;
for (locals.i = 0; locals.i < state._participantCount; ++locals.i)
{
locals.p = state._participants.get(locals.i);
locals.found = false;
for (locals.j = 0; locals.j < locals.uniqueCount; ++locals.j)
{
if (output.participants.get(locals.j) == locals.p)
{
output.ticketCounts.set(locals.j, output.ticketCounts.get(locals.j) + 1);
locals.found = true;
break;
}
}
if (!locals.found)
{
output.participants.set(locals.uniqueCount, locals.p);
output.ticketCounts.set(locals.uniqueCount, 1);
++locals.uniqueCount;
}
}
output.participantCount = state._participantCount;
output.uniqueParticipantCount = locals.uniqueCount;
}

REGISTER_USER_FUNCTIONS_AND_PROCEDURES()
{
REGISTER_USER_PROCEDURE(buyTicket, 1);
REGISTER_USER_FUNCTION(getInfo, 2);
REGISTER_USER_FUNCTION(getParticipants, 3);
}

INITIALIZE()
{
state._participantCount = 0;
state._pot = 0;
state._lastWinAmount = 0;
state._lastWinner = NULL_ID;
state._lastDrawHour = qpi.hour();
state._owner = ID(_Q, _D, _R, _A, _W, _U, _R, _A, _L, _C, _L, _P, _P, _E, _Q, _O, _G, _Q, _C, _U, _J, _N, _F, _B, _B, _B, _A, _A, _F, _X, _W, _Y, _Y, _M, _M, _C, _U, _C, _U, _K, _T, _C, _R, _Q, _B, _S, _M, _Z, _U, _D, _M, _V, _X, _P, _N, _F);
}

BEGIN_TICK_WITH_LOCALS()
{
locals.currentHour = qpi.hour();
if (locals.currentHour != state._lastDrawHour)
{
state._lastDrawHour = locals.currentHour;
if (state._participantCount > 0)
{
if (isMonopoly(state._participants, state._participantCount, locals.loopIndex))
{
locals.only = state._participants.get(0);
qpi.burn(QDRAW_TICKET_PRICE);
qpi.transfer(locals.only, QDRAW_TICKET_PRICE);
qpi.transfer(state._owner, state._pot - QDRAW_TICKET_PRICE - QDRAW_TICKET_PRICE);
state._lastWinner = locals.only;
state._lastWinAmount = QDRAW_TICKET_PRICE;
}
else
{
locals.rand = qpi.K12(qpi.getPrevSpectrumDigest());
locals.winner = state._participants.get(mod(locals.rand.u64._0, state._participantCount));
qpi.transfer(locals.winner, state._pot);
state._lastWinner = locals.winner;
state._lastWinAmount = state._pot;
}
state._participantCount = 0;
state._pot = 0;
}
}
}
};


Loading
Loading