Skip to content
Open
Show file tree
Hide file tree
Changes from 9 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
7 changes: 5 additions & 2 deletions src/contract_core/contract_def.h

Copy link
Copy Markdown
Contributor

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
Contributor

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 @@ -417,7 +417,7 @@ 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
// new contracts should be added above this line
#ifdef INCLUDE_CONTRACT_TEST_EXAMPLES
Expand Down Expand Up @@ -557,7 +557,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 +568,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
258 changes: 258 additions & 0 deletions src/contracts/Qassand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
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 sint64 QASSAND_PING_FEE = 100000;
constexpr sint64 QASSAND_PROTOCOL_FEE = 75000;
constexpr sint64 QASSAND_BURN_FEE = 25000;
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
Contributor

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;
sint64 pingFee;
sint64 protocolFee;
sint64 burnFee;
uint64 totalPingCount;
sint64 protocolEarnedFee;
sint64 burnEarnedFee;
sint64 pendingBurnAmount;
sint64 totalBurnedAmount;
};

struct Ping_input
{
};

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

struct Ping_locals
{
sint64 paidAmount;
sint64 refundAmount;
};

struct GetInfo_input
{
};

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

struct GetFeeInfo_input
{
};

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

struct GetBurnInfo_input
{
};

struct GetBurnInfo_output
{
sint64 pendingBurnAmount;
sint64 totalBurnedAmount;
};

struct GetLaneInfo_input
{
uint16 laneId;
};

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

struct END_TICK_locals
{
sint64 burnAmount;
};

INITIALIZE()
{
state.mut().version = QASSAND_VERSION;
state.mut().constructionEpoch = QASSAND_CONSTRUCTION_EPOCH_PLACEHOLDER;
state.mut().pingFee = QASSAND_PING_FEE;
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().pingFee)
{
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().pingFee;
if (locals.refundAmount > 0)
{
qpi.transfer(qpi.invocator(), locals.refundAmount);
}

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

Copy link
Copy Markdown
Contributor

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().pingFee;
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().pingFee;
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;
}
};
1 change: 1 addition & 0 deletions test/CMakeLists.txt

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this file should not be changed

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thank you, fixed.
I registered the existing Qassand contract and test source in the Visual Studio project files, and restored the Qassand contract registration in contract_def.h using index 29 to avoid the existing GGWP/WOLFPACK index 28.
Also,
I reviewed the signed integer usage and changed fee / amount-style values that cannot be negative to unsigned types. And changed the fee handling so the ping fee is derived from protocolFee + burnFee instead of being maintained as an independent stored state value.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

TY, fixed.
I reverted the test/CMakeLists.txt change so that file is no longer modified by this PR. The Qassand contract and test source remain registered only in the Visual Studio project files.

Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ add_executable(
# contract_qearn.cpp
# contract_qvault.cpp
# contract_qx.cpp
contract_qassand.cpp
contract_qraffle.cpp
contract_vottunbridge.cpp
# kangaroo_twelve.cpp
Expand Down
Loading
Loading