Contracts in SparqNet
Contracts in SparqNet
Contracts in Sparq work similar to Solidity contracts - developers can implement diverse logic structures within the network, and directly interact with the blockchain's current state. The main difference is, in Sparq, contracts are native, compiled C++ code, taking advantage of the absence of an EVM and its constraints, having full control of the contract's logic and unleashing blazing fast performance.
This chapter will comprehensively cover creating new contracts for Sparq using OrbiterSDK. Generally, to create a contract from scratch, you must:
Develop the contract's logic in C++
Manually code several methods to parse arguments of transactions calling your contract
Use a database to manage the storage of your local variables
The rules explained throughout this chapter ensure that contracts remain compatible with frontend Web3 tools (e.g. MetaMask, ethers.js, web3.js, etc.). Those are designed to interact with Solidity contracts and thus require a similar interface.
To call your contract's functions from a frontend, you can replicate their definitions in Solidity and generate the ABI using our generator tool (explained further), or an external tool like Ethereum's Remix or any other of your preference. This ABI can then be used with your preferred Web3 frontend.
Types of Contracts
OrbiterSDK offers two types of contracts: Dynamic Contracts and Protocol Contracts. The differences between them primarily come from how they are created and managed within the SDK.
Dynamic Contracts (recommended)
Can only be handled by the
ContractManager
class (see below), which enables the chain owner to create an unlimited number of Dynamic ContractsCan use Safe Variables - an additional layer of protection that allows better control over whether their changes are committed to the state or automatically reverted when necessary (e.g. when a transaction fails)
Can only be called when a block is being processed
Are directly loaded into memory and work very similarly to Solidity contracts
OrbiterSDK provides ready-to-use templates for the following Dynamic Contracts:
ERC20
,ERC20Wrapper
, andNativeWrapper
Protocol Contracts
Are directly integrated into the blockchain, therefore not linked to the
ContractManager
class and not contained by it, which removes some restrictions but adds others (see 3-6)Cannot use Safe Variables as they only work with Dynamic Contracts - so it's all up to you (for the most part) as to where to place the contract's variables and their commit/revert logic within the source code of the blockchain
The ContractManager class
The ContractManager
class (declared in src/contract/contractmanager.h
) is a Protocol Contract, responsible for:
Handling all the logic related to creating and loading Dynamic Contracts registered within the blockchain (which you can get a list of by calling the class'
getContractList()
function - it returns an(address[], string[])
map with the currently registered contracts)Managing global variables for contracts, such as the contract's name, address, owner, and balance
Calling any function registered within your contract if the functor/signature matches
Automatically committing/reverting changes made to the account state when necessary (for non-view functions)
The ContractManager
is the class that holds all the current contract instances in the State, besides being the access point for contracts to access other contracts. It's header should be similar to the following:
The contract manager will be responsible for deploying the contracts in the chain, loading them from DB when constructing and saving them to DB when deconstructing. The function processTransaction
would be similar to this
Example Contract
Giving the example Solidity contract:
The transpiled code should look similar to this:
Declaration
Definition
The Contract base class
The Contract class, declared in contract/contract.h, is the base class which all contracts derive from. This class holds all the Solidity global variables, besides variables common among these contracts (such as contract Address). Its header should look similar to the following:
Regarding the callContractWithTransaction
and the ethCallContract
functions, callContractWithTransaction
is used by the State when calling from processNewBlock()
, while ethCallContract
is used by RPC to answer for eth_call
. Strings returned by ethCallContract
are hex strings encoded with the desired function result.
Last updated