Skip to content

Commit

Permalink
SimpleContract: add usage of SafeTuple
Browse files Browse the repository at this point in the history
  • Loading branch information
Jean-Lessa committed Jan 30, 2024
1 parent be5e003 commit e20dde6
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 49 deletions.
33 changes: 28 additions & 5 deletions src/contract/templates/simplecontract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,48 @@ See the LICENSE.txt file in the project root for more information.
SimpleContract::SimpleContract(
const std::string& name,
const uint256_t& value,
const std::tuple<std::string, uint256_t>& tuple,
ContractManagerInterface &interface,
const Address& address,
const Address& creator,
const uint64_t& chainId,
const std::unique_ptr<DB> &db
) : DynamicContract(interface, "SimpleContract", address, creator, chainId, db), name_(this), value_(this) {
) : DynamicContract(interface, "SimpleContract", address, creator, chainId, db),
name_(this), value_(this), tuple_(this)
{
this->name_ = name;
this->value_ = value;
this->tuple_ = tuple;
registerContractFunctions();
}

SimpleContract::SimpleContract(
ContractManagerInterface &interface,
const Address& address,
const std::unique_ptr<DB> &db
) : DynamicContract(interface, address, db), name_(this), value_(this) {
) : DynamicContract(interface, address, db), name_(this), value_(this), tuple_(this) {
this->name_ = Utils::bytesToString(db->get(std::string("name_"), this->getDBPrefix()));
this->value_ = Utils::bytesToUint256(db->get(std::string("value_"), this->getDBPrefix()));
this->tuple_ = std::make_tuple(
Utils::bytesToString(db->get(std::string("tuple_name"), this->getDBPrefix())),
Utils::bytesToUint256(db->get(std::string("tuple_value"), this->getDBPrefix()))
);
registerContractFunctions();
}

SimpleContract::~SimpleContract() {
this->db_->put(std::string("name_"), Utils::stringToBytes(this->name_.get()), this->getDBPrefix());
this->db_->put(std::string("value_"), Utils::uint256ToBytes(this->value_.get()), this->getDBPrefix());
return;
this->db_->put(std::string("tuple_name"), Utils::stringToBytes(get<0>(this->tuple_)), this->getDBPrefix());
this->db_->put(std::string("tuple_value"), Utils::uint256ToBytes(get<1>(this->tuple_)), this->getDBPrefix());
}

void SimpleContract::setName(const std::string& argName) {
if (this->getCaller() != this->getContractCreator()) {
throw std::runtime_error("Only contract creator can call this function.");
}
this->name_ = argName;
this->nameChanged(argName);
this->nameChanged(this->name_.get());
}

void SimpleContract::setNames(const std::vector<std::string>& argName) {
Expand All @@ -59,7 +68,7 @@ void SimpleContract::setValue(const uint256_t& argValue) {
throw std::runtime_error("Only contract creator can call this function.");
}
this->value_ = argValue;
this->valueChanged(argValue);
this->valueChanged(this->value_.get());
}

void SimpleContract::setValues(const std::vector<uint256_t>& argValue) {
Expand Down Expand Up @@ -107,6 +116,14 @@ void SimpleContract::setNamesAndValuesInArrayOfArrays(
this->nameAndValueChanged(this->name_.get(), this->value_.get());
}

void SimpleContract::setTuple(const std::tuple<std::string, uint256_t>& argTuple) {
if (this->getCaller() != this->getContractCreator()) {
throw std::runtime_error("Only contract creator can call this function.");
}
this->tuple_ = argTuple;
this->tupleChanged(std::make_tuple(get<0>(this->tuple_), get<1>(this->tuple_)));
}

std::string SimpleContract::getName() const { return this->name_.get(); }

std::vector<std::string> SimpleContract::getNames(const uint256_t& i) const {
Expand Down Expand Up @@ -164,6 +181,10 @@ SimpleContract::getNamesAndValuesInArrayOfArrays(const uint256_t& i) const {
return namesAndValues;
}

std::tuple<std::string, uint256_t> SimpleContract::getTuple() const {
return std::make_tuple(get<0>(this->tuple_), get<1>(this->tuple_));
}

void SimpleContract::registerContractFunctions() {
registerContract();
this->registerMemberFunction("setName", &SimpleContract::setName, FunctionTypes::NonPayable, this);;
Expand All @@ -173,6 +194,7 @@ void SimpleContract::registerContractFunctions() {
this->registerMemberFunction("setNamesAndValues", &SimpleContract::setNamesAndValues, FunctionTypes::NonPayable, this);
this->registerMemberFunction("setNamesAndValuesInTuple", &SimpleContract::setNamesAndValuesInTuple, FunctionTypes::NonPayable, this);
this->registerMemberFunction("setNamesAndValuesInArrayOfArrays", &SimpleContract::setNamesAndValuesInArrayOfArrays, FunctionTypes::NonPayable, this);
this->registerMemberFunction("setTuple", &SimpleContract::setTuple, FunctionTypes::NonPayable, this);
this->registerMemberFunction("getName", &SimpleContract::getName, FunctionTypes::View, this);
this->registerMemberFunction("getNames", &SimpleContract::getNames, FunctionTypes::View, this);
this->registerMemberFunction("getValue", static_cast<uint256_t(SimpleContract::*)() const>(&SimpleContract::getValue), FunctionTypes::View, this);
Expand All @@ -182,5 +204,6 @@ void SimpleContract::registerContractFunctions() {
this->registerMemberFunction("getNamesAndValues", &SimpleContract::getNamesAndValues, FunctionTypes::View, this);
this->registerMemberFunction("getNamesAndValuesInTuple", &SimpleContract::getNamesAndValuesInTuple, FunctionTypes::View, this);
this->registerMemberFunction("getNamesAndValuesInArrayOfArrays", &SimpleContract::getNamesAndValuesInArrayOfArrays, FunctionTypes::View, this);
this->registerMemberFunction("getTuple", &SimpleContract::getTuple, FunctionTypes::View, this);
}

31 changes: 26 additions & 5 deletions src/contract/templates/simplecontract.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ See the LICENSE.txt file in the project root for more information.

#include "../dynamiccontract.h"
#include "../variables/safestring.h"
#include "../variables/safetuple.h"
#include "../../utils/utils.h" // SafeUintX_t aliases declared here

/**
Expand All @@ -20,15 +21,21 @@ class SimpleContract : public DynamicContract {
private:
SafeString name_; ///< The name of the contract.
SafeUint256_t value_; ///< The value of the contract.
SafeTuple<std::string, uint256_t> tuple_; ///< Name and value as a tuple.
void registerContractFunctions() override; ///< Register the contract functions.

public:
/// Event for when the name changes.
void nameChanged(const EventParam<std::string, true>& name) { this->emitEvent(__func__, std::make_tuple(name)); }
void nameChanged(const EventParam<std::string, true>& name) { this->emitEvent(__func__, std::make_tuple(name)); }

/// Event for when the value changes.
void valueChanged(const EventParam<uint256_t, false>& value) { this->emitEvent(__func__, std::make_tuple(value)); }

/// Event for when the name and value tuple changes.
void tupleChanged(const EventParam<std::tuple<std::string, uint256_t>, true>& tuple) {
this->emitEvent(__func__, std::make_tuple(tuple));
}

/// Event for when the name and value change. Used for testing JSON ABI generation.
void nameAndValueChanged(const EventParam<std::string, true>& name, const EventParam<uint256_t, true>& value) {
this->emitEvent(__func__, std::make_tuple(name, value));
Expand All @@ -39,12 +46,16 @@ class SimpleContract : public DynamicContract {
this->emitEvent(__func__, std::make_tuple(nameAndValue));
}

using ConstructorArguments = std::tuple<const std::string&, const uint256_t&>; ///< The constructor arguments type.
/// The constructor argument types.
using ConstructorArguments = std::tuple<
const std::string&, const uint256_t&, const std::tuple<std::string, uint256_t>&
>;

/**
* Constructor from create. Create contract and save it to database.
* @param name The name of the contract.
* @param value The value of the contract.
* @param tuple The name and value tuple of the contract.
* @param interface The interface to the contract manager.
* @param address The address of the contract.
* @param creator The address of the creator of the contract.
Expand All @@ -54,6 +65,7 @@ class SimpleContract : public DynamicContract {
SimpleContract(
const std::string& name,
const uint256_t& value,
const std::tuple<std::string, uint256_t>& tuple,
ContractManagerInterface &interface,
const Address& address,
const Address& creator,
Expand Down Expand Up @@ -99,6 +111,9 @@ class SimpleContract : public DynamicContract {
/// the final name is the concatenation of all names, the final value is the sum of all values
void setNamesAndValuesInArrayOfArrays(const std::vector<std::vector<std::tuple<std::string, uint256_t>>>& argNameAndValue);

/// equivalent to function setTuple(string name, uint256 value) public
void setTuple(const std::tuple<std::string, uint256_t>& argTuple);

/// function getName() public view returns(string memory)
std::string getName() const;

Expand Down Expand Up @@ -130,22 +145,26 @@ class SimpleContract : public DynamicContract {
/// return (string, uint256)[][] of size i with this->name_ and this->value_ as all elements.
std::vector<std::vector<std::tuple<std::string, uint256_t>>> getNamesAndValuesInArrayOfArrays(const uint256_t& i) const;

/// equivalent to function getTuple() public view returns(string memory, uint256)
std::tuple<std::string, uint256_t> getTuple() const;

/// Register the contract structure.
static void registerContract() {
ContractReflectionInterface::registerContractMethods<
SimpleContract, const std::string&, uint256_t,
SimpleContract, const std::string&, const uint256_t&, const std::tuple<std::string, uint256_t>&,
ContractManagerInterface&,
const Address&, const Address&, const uint64_t&,
const std::unique_ptr<DB>&
>(
std::vector<std::string>{"name_", "value_"},
std::vector<std::string>{"name_", "value_", "tuple_"},
std::make_tuple("setName", &SimpleContract::setName, FunctionTypes::NonPayable, std::vector<std::string>{"argName"}),
std::make_tuple("setNames", &SimpleContract::setNames, FunctionTypes::NonPayable, std::vector<std::string>{"argName"}),
std::make_tuple("setValue", &SimpleContract::setValue, FunctionTypes::NonPayable, std::vector<std::string>{"argValue"}),
std::make_tuple("setValues", &SimpleContract::setValues, FunctionTypes::NonPayable, std::vector<std::string>{"argValue"}),
std::make_tuple("setNamesAndValues", &SimpleContract::setNamesAndValues, FunctionTypes::NonPayable, std::vector<std::string>{"argName", "argValue"}),
std::make_tuple("setNamesAndValuesInTuple", &SimpleContract::setNamesAndValuesInTuple, FunctionTypes::NonPayable, std::vector<std::string>{"argNameAndValue"}),
std::make_tuple("setNamesAndValuesInArrayOfArrays", &SimpleContract::setNamesAndValuesInArrayOfArrays, FunctionTypes::NonPayable, std::vector<std::string>{"argNameAndValue"}),
std::make_tuple("setTuple", &SimpleContract::setTuple, FunctionTypes::NonPayable, std::vector<std::string>{"argTupĺe"}),
std::make_tuple("getName", &SimpleContract::getName, FunctionTypes::View, std::vector<std::string>{}),
std::make_tuple("getNames", &SimpleContract::getNames, FunctionTypes::View, std::vector<std::string>{"i"}),
std::make_tuple("getValue", static_cast<uint256_t(SimpleContract::*)() const>(&SimpleContract::getValue), FunctionTypes::View, std::vector<std::string>{}),
Expand All @@ -154,11 +173,13 @@ class SimpleContract : public DynamicContract {
std::make_tuple("getNameAndValue", &SimpleContract::getNameAndValue, FunctionTypes::View, std::vector<std::string>{}),
std::make_tuple("getNamesAndValues", &SimpleContract::getNamesAndValues, FunctionTypes::View, std::vector<std::string>{"i"}),
std::make_tuple("getNamesAndValuesInTuple", &SimpleContract::getNamesAndValuesInTuple, FunctionTypes::View, std::vector<std::string>{"i"}),
std::make_tuple("getNamesAndValuesInArrayOfArrays", &SimpleContract::getNamesAndValuesInArrayOfArrays, FunctionTypes::View, std::vector<std::string>{"i"})
std::make_tuple("getNamesAndValuesInArrayOfArrays", &SimpleContract::getNamesAndValuesInArrayOfArrays, FunctionTypes::View, std::vector<std::string>{"i"}),
std::make_tuple("getTuple", &SimpleContract::getTuple, FunctionTypes::View, std::vector<std::string>{})
);
ContractReflectionInterface::registerContractEvents<SimpleContract>(
std::make_tuple("nameChanged", false, &SimpleContract::nameChanged, std::vector<std::string>{"name"}),
std::make_tuple("valueChanged", false, &SimpleContract::valueChanged, std::vector<std::string>{"value"}),
std::make_tuple("tupleChanged", false, &SimpleContract::tupleChanged, std::vector<std::string>{"tuple"}),
std::make_tuple("nameAndValueChanged", false, &SimpleContract::nameAndValueChanged, std::vector<std::string>{"name", "value"}),
std::make_tuple("nameAndValueTupleChanged", false, &SimpleContract::nameAndValueTupleChanged, std::vector<std::string>{"nameAndValue"})
);
Expand Down
8 changes: 7 additions & 1 deletion src/contract/variables/safetuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,13 @@ template<typename... Types> class SafeTuple : public SafeBase {
template <typename... OtherTypes> friend class SafeTuple;

public:
SafeTuple() : tuple_() {} ///< Default constructor.
SafeTuple() : SafeBase(nullptr), tuple_() {} ///< Empty constructor.

/**
* Constructor with owner, also empty.
* @param owner The contract that owns the variable.
*/
SafeTuple(DynamicContract* owner) : SafeBase(owner), tuple_() {}

/**
* Forward declaration constructor.
Expand Down
10 changes: 8 additions & 2 deletions tests/contract/contractabigenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ TEST_CASE("ContractABIGenerator helper", "[contract][contractabigenerator]") {
std::ifstream i("ABI/SimpleContract.json");
i >> j;

REQUIRE(j.size() == 20);
REQUIRE(j.size() == 23);
auto findSetName = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::setName);
REQUIRE(findSetName != j.end());
auto findSetNames = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::setNames);
Expand All @@ -130,6 +130,8 @@ TEST_CASE("ContractABIGenerator helper", "[contract][contractabigenerator]") {
REQUIRE(findSetNamesAndValuesInTuple != j.end());
auto findSetNamesAndValuesInArrayOfArrays = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::setNamesAndValuesInArrayOfArrays);
REQUIRE(findSetNamesAndValuesInArrayOfArrays != j.end());
auto findSetTuple = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::setTuple);
REQUIRE(findSetTuple != j.end());
auto findGetName = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::getName);
REQUIRE(findGetName != j.end());
auto findGetNames = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::getNames);
Expand All @@ -146,6 +148,8 @@ TEST_CASE("ContractABIGenerator helper", "[contract][contractabigenerator]") {
REQUIRE(findGetNamesAndValuesInTuple != j.end());
auto findGetNamesAndValuesInArrayOfArrays = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::getNamesAndValuesInArrayOfArrays);
REQUIRE(findGetNamesAndValuesInArrayOfArrays != j.end());
auto findGetTuple = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::getTuple);
REQUIRE(findGetTuple != j.end());
auto findGetValueOverload = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::getValueOverload);
REQUIRE(findGetValueOverload != j.end());
auto findNameAndValueTupleChanged = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::nameAndValueTupleChanged);
Expand All @@ -156,6 +160,8 @@ TEST_CASE("ContractABIGenerator helper", "[contract][contractabigenerator]") {
REQUIRE(findValueChanged != j.end());
auto findNameChanged = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::nameChanged);
REQUIRE(findNameChanged != j.end());
auto findTupleChanged = std::find(j.begin(), j.end(), EXPECTED::SimpleContract::tupleChanged);
REQUIRE(findTupleChanged != j.end());
}

SECTION("ContractABIGenerator getFunctionName") {
Expand All @@ -164,4 +170,4 @@ TEST_CASE("ContractABIGenerator helper", "[contract][contractabigenerator]") {
REQUIRE(ContractReflectionInterface::getFunctionName(&NativeWrapper::transfer) == "transfer");
REQUIRE(ContractReflectionInterface::getFunctionName(&ERC20::transfer) == "transfer");
}
}
}
Loading

0 comments on commit e20dde6

Please sign in to comment.