Skip to content
Open
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
3 changes: 2 additions & 1 deletion src/Qubic.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
<ClInclude Include="contracts\MsVault.h" />
<ClInclude Include="contracts\MyLastMatch.h" />
<ClInclude Include="contracts\qpi.h" />
<ClInclude Include="contracts\Quottery.h" />
<ClInclude Include="contracts\Quottery.h" />
<ClInclude Include="contracts\Qassand.h" />
<ClInclude Include="contracts\QUtil.h" />
<ClInclude Include="contracts\Qx.h" />
<ClInclude Include="contracts\Random.h" />
Expand Down
3 changes: 3 additions & 0 deletions src/Qubic.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@
</ClInclude>
<ClInclude Include="contracts\Quottery.h">
<Filter>contracts</Filter>
</ClInclude>
<ClInclude Include="contracts\Qassand.h">
<Filter>contracts</Filter>
</ClInclude>
<ClInclude Include="contracts\MsVault.h">
<Filter>contracts</Filter>
Expand Down
19 changes: 17 additions & 2 deletions src/contract_core/contract_def.h

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you did to this file but the diff shows changes in all lines (line ending change?). please restore the original version and make sure that the commit only affects the lines where you actually added code for your contract.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please follow the docs and add all required changes for your new contract in contract_def.h (see https://github.com/qubic/core/blob/main/doc/contracts.md#development)

Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,16 @@

#endif

#undef CONTRACT_INDEX
#undef CONTRACT_STATE_TYPE
#undef CONTRACT_STATE2_TYPE

#define QASSAND_CONTRACT_INDEX 29
#define CONTRACT_INDEX QASSAND_CONTRACT_INDEX
#define CONTRACT_STATE_TYPE QASSAND
#define CONTRACT_STATE2_TYPE QASSAND2
#include "contracts/Qassand.h"

// new contracts should be added above this line

#ifdef INCLUDE_CONTRACT_TEST_EXAMPLES
Expand Down Expand Up @@ -417,8 +427,9 @@ constexpr struct ContractDescription
{"QUSINO", 208, 10000, sizeof(QUSINO::StateData)}, // proposal in epoch 206, IPO in 207, construction and first use in 208
{"ESCROW", 210, 10000, sizeof(ESCROW::StateData)}, // proposal in epoch 208, IPO in 209, construction and first use in 210
#ifndef NO_GGWP
{"GGWP", 217, 10000, sizeof(WOLFPACK::StateData)}, // proposal in epoch 215, IPO in 216, construction and first use in 217
{"GGWP", 218, 10000, sizeof(WOLFPACK::StateData)}, // proposal in epoch 216, IPO in 217, construction and first use in 218
#endif
{"QASSAND", QASSAND_CONSTRUCTION_EPOCH_PLACEHOLDER, 10000, sizeof(QASSAND::StateData)},
// new contracts should be added above this line
#ifdef INCLUDE_CONTRACT_TEST_EXAMPLES
{"TESTEXA", 138, 10000, sizeof(TESTEXA::StateData)},
Expand Down Expand Up @@ -545,6 +556,7 @@ static void initializeContracts()
#ifndef NO_GGWP
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(WOLFPACK);
#endif
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(QASSAND);
// new contracts should be added above this line
#ifdef INCLUDE_CONTRACT_TEST_EXAMPLES
REGISTER_CONTRACT_FUNCTIONS_AND_PROCEDURES(TESTEXA);
Expand All @@ -557,7 +569,9 @@ static void initializeContracts()
// Automatic Contract State Changes
enum ContractStateChangeType
{
// Keeps the saved state's old bytes, only zero-fills the new bytes at the end (used when struct grew; old fields preserved)
PADDING,
// Discards the saved state entirely, zeros the whole buffer
RESET,
};
struct ContractStateChangeInfo
Expand All @@ -566,8 +580,9 @@ struct ContractStateChangeInfo
ContractStateChangeType changeType;
};
// Contracts whose state struct changed this epoch. Update this list each epoch as needed.
// Each entry is { CONTRACT_INDEX, PADDING or RESET }
// When enabling, replace both lines below, e.g.:
constexpr ContractStateChangeInfo contractStateChangeInfos[] = { { QIP_CONTRACT_INDEX, RESET } };
constexpr ContractStateChangeInfo contractStateChangeInfos[] = { {RANDOM_CONTRACT_INDEX, PADDING} };
constexpr unsigned int contractStateChangeCount = sizeof(contractStateChangeInfos) / sizeof(contractStateChangeInfos[0]);
// constexpr const ContractStateChangeInfo* contractStateChangeInfos = nullptr;
// constexpr unsigned int contractStateChangeCount = 0;
Expand Down
256 changes: 256 additions & 0 deletions src/contracts/Qassand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
using namespace QPI;

// QASSAND is the Qubic contract implementation name for the Qassandra protocol v0.
constexpr uint16 QASSAND_VERSION = 0;
constexpr uint16 QASSAND_CONSTRUCTION_EPOCH_PLACEHOLDER = 10000;
constexpr uint64 QASSAND_PROTOCOL_FEE = 75000;
constexpr uint64 QASSAND_BURN_FEE = 25000;
constexpr uint64 QASSAND_PING_FEE = QASSAND_PROTOCOL_FEE + QASSAND_BURN_FEE;
constexpr uint8 QASSAND_SUCCESS = 0;
constexpr uint8 QASSAND_UNDERPAID = 1;
constexpr uint8 QASSAND_UNKNOWN_LANE = 2;
constexpr uint16 QASSAND_LANE_UNKNOWN = 0;
constexpr uint16 QASSAND_LANE_FORECASTING = 1;
constexpr uint16 QASSAND_LANE_STABLE_OPERATIONS = 2;
constexpr uint16 QASSAND_LANE_DATA_ATTESTATION = 3;

struct QASSAND2
{
};

struct QASSAND : public ContractBase
{
struct StateData

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for some of these variables, it does not really make sense that they are signed integers because naturally they will always ne non-negative (e.g. fees, amounts). please double-check which variables need to be signed/unsigned.

{
uint16 version;
uint16 constructionEpoch;
uint64 protocolFee;
uint64 burnFee;
uint64 totalPingCount;
uint64 protocolEarnedFee;
uint64 burnEarnedFee;
uint64 pendingBurnAmount;
uint64 totalBurnedAmount;
};

struct Ping_input
{
};

struct Ping_output
{
uint8 returnCode;
uint64 acceptedFee;
uint64 refundedAmount;
uint64 protocolEarnedFee;
uint64 burnEarnedFee;
uint64 totalPingCount;
};

struct Ping_locals
{
uint64 paidAmount;
uint64 refundAmount;
};

struct GetInfo_input
{
};

struct GetInfo_output
{
Array<uint8, 16> protocolName;
uint16 version;
uint16 constructionEpoch;
uint64 totalPingCount;
};

struct GetFeeInfo_input
{
};

struct GetFeeInfo_output
{
uint64 pingFee;
uint64 protocolFee;
uint64 burnFee;
uint64 protocolEarnedFee;
uint64 burnEarnedFee;
};

struct GetBurnInfo_input
{
};

struct GetBurnInfo_output
{
uint64 pendingBurnAmount;
uint64 totalBurnedAmount;
};

struct GetLaneInfo_input
{
uint16 laneId;
};

struct GetLaneInfo_output
{
uint8 returnCode;
uint16 laneId;
Array<uint8, 16> laneName;
uint64 requiredFee;
};

struct END_TICK_locals
{
uint64 burnAmount;
};

INITIALIZE()
{
state.mut().version = QASSAND_VERSION;
state.mut().constructionEpoch = QASSAND_CONSTRUCTION_EPOCH_PLACEHOLDER;
state.mut().protocolFee = QASSAND_PROTOCOL_FEE;
state.mut().burnFee = QASSAND_BURN_FEE;
}

REGISTER_USER_FUNCTIONS_AND_PROCEDURES()
{
REGISTER_USER_PROCEDURE(Ping, 1);
REGISTER_USER_FUNCTION(GetInfo, 1);
REGISTER_USER_FUNCTION(GetFeeInfo, 2);
REGISTER_USER_FUNCTION(GetBurnInfo, 3);
REGISTER_USER_FUNCTION(GetLaneInfo, 4);
}

END_TICK_WITH_LOCALS()
{
locals.burnAmount = state.get().pendingBurnAmount;
if (locals.burnAmount == 0)
{
return;
}

qpi.burn(locals.burnAmount);
state.mut().pendingBurnAmount = 0;
state.mut().totalBurnedAmount += locals.burnAmount;
}

PUBLIC_PROCEDURE_WITH_LOCALS(Ping)
{
locals.paidAmount = qpi.invocationReward();

if (locals.paidAmount < (state.get().protocolFee + state.get().burnFee))
{
if (locals.paidAmount != 0)
{
qpi.transfer(qpi.invocator(), locals.paidAmount);
}
output.returnCode = QASSAND_UNDERPAID;
output.refundedAmount = locals.paidAmount;
return;
}

locals.refundAmount = locals.paidAmount - (state.get().protocolFee + state.get().burnFee);
if (locals.refundAmount != 0)
{
qpi.transfer(qpi.invocator(), locals.refundAmount);
}

state.mut().totalPingCount += 1;
state.mut().protocolEarnedFee += state.get().protocolFee;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see in your definitions at the beginning of the file that the amounts for protocolFee and burnFee add up to pingFee. with this context, the code here is correct. however, it is not guaranteed in the code that pingFee = protocolFee + burnFee so changing any of the fees independently could easily lead to bugs in the future.

state.mut().burnEarnedFee += state.get().burnFee;
state.mut().pendingBurnAmount += state.get().burnFee;

output.returnCode = QASSAND_SUCCESS;
output.acceptedFee = (state.get().protocolFee + state.get().burnFee);
output.refundedAmount = locals.refundAmount;
output.protocolEarnedFee = state.get().protocolFee;
output.burnEarnedFee = state.get().burnFee;
output.totalPingCount = state.get().totalPingCount;
}

PUBLIC_FUNCTION(GetInfo)
{
output.protocolName.set(0, 81);
output.protocolName.set(1, 97);
output.protocolName.set(2, 115);
output.protocolName.set(3, 115);
output.protocolName.set(4, 97);
output.protocolName.set(5, 110);
output.protocolName.set(6, 100);
output.protocolName.set(7, 114);
output.protocolName.set(8, 97);
output.version = state.get().version;
output.constructionEpoch = state.get().constructionEpoch;
output.totalPingCount = state.get().totalPingCount;
}

PUBLIC_FUNCTION(GetFeeInfo)
{
output.pingFee = (state.get().protocolFee + state.get().burnFee);
output.protocolFee = state.get().protocolFee;
output.burnFee = state.get().burnFee;
output.protocolEarnedFee = state.get().protocolEarnedFee;
output.burnEarnedFee = state.get().burnEarnedFee;
}

PUBLIC_FUNCTION(GetBurnInfo)
{
output.pendingBurnAmount = state.get().pendingBurnAmount;
output.totalBurnedAmount = state.get().totalBurnedAmount;
}

PUBLIC_FUNCTION(GetLaneInfo)
{
if (input.laneId == QASSAND_LANE_FORECASTING)
{
output.returnCode = QASSAND_SUCCESS;
output.laneId = QASSAND_LANE_FORECASTING;
output.laneName.set(0, 70);
output.laneName.set(1, 111);
output.laneName.set(2, 114);
output.laneName.set(3, 101);
output.laneName.set(4, 99);
output.laneName.set(5, 97);
output.laneName.set(6, 115);
output.laneName.set(7, 116);
output.laneName.set(8, 105);
output.laneName.set(9, 110);
output.laneName.set(10, 103);
output.requiredFee = 0;
return;
}

if (input.laneId == QASSAND_LANE_STABLE_OPERATIONS)
{
output.returnCode = QASSAND_SUCCESS;
output.laneId = QASSAND_LANE_STABLE_OPERATIONS;
output.laneName.set(0, 83);
output.laneName.set(1, 116);
output.laneName.set(2, 97);
output.laneName.set(3, 98);
output.laneName.set(4, 108);
output.laneName.set(5, 101);
output.laneName.set(6, 79);
output.laneName.set(7, 112);
output.laneName.set(8, 115);
output.requiredFee = 0;
return;
}

if (input.laneId == QASSAND_LANE_DATA_ATTESTATION)
{
output.returnCode = QASSAND_SUCCESS;
output.laneId = QASSAND_LANE_DATA_ATTESTATION;
output.laneName.set(0, 68);
output.laneName.set(1, 97);
output.laneName.set(2, 116);
output.laneName.set(3, 97);
output.requiredFee = 0;
return;
}

output.returnCode = QASSAND_UNKNOWN_LANE;
}
};
Loading