First Things First
Before embarking on developing a Smart Contract on the Stratis Platform, you will need to have a local environment which you can test and deploy on, to simplify this, a bootstrapped environment can be utilized by installing the Cirrus Core (Developer Edition) wallet.
This small local network uses a Proof-of-Authority (PoA) consensus algorithm. This network runs completely standalone, however more nodes can join the network by simply opening another instance of Cirrus Core (Developer Edition) locally.
A significant amount of focus has been put into simplifying the ‘setup’ process and to ensure a consistent development environment for those looking to embark on Smart Contract Development in C#.
A tutorial is available on the Stratis Academy that will help you get started.
There is also a GUI that can be used to aid the development process, a seperate operating guide can be found here.
The Stratis smart contract platform runs smart contracts written in the C# language. Contracts run natively on the .NET Core CLR. There are significant and important differences between writing a C# smart contract and writing regular C# code that developers should be aware of.
Working with Smart Contracts
Writing and deploying a contract involves several different tools and processes. Before a contract can be deployed, it must be validated to ensure it conforms to determinism and format requirements.
Afterwards, it can be compiled to bytecode and deployed on chain. Both these steps can be performed using the Smart Contract Tool (SCT), available at https://github.com/stratisproject/Stratis.SmartContracts.Tools.Sct/ and included in the Developer Edition wallet distribution in the SDK folder.
The recommended way to deploy and interact with your contracts is by using the Developer Edition wallet. This simplifies the process of creating and broadcasting transactions to the blockchain.
You may also wish to interact with your contract via an API. This approach is discussed more below.
Read more about working with contracts here: https://academy.stratisplatform.com/Architecture%20Reference/SmartContracts/working-with-contracts.html
Differences with regular C#
Smart contracts must execute deterministically (within a public environment), which means that every time they run they must always produce the same result.
The subset of C# that can be used has necessarily been limited. This means that no external libraries and very few core classes are available to developers. Floating point arithmetic is not supported. It’s not possible to instantiate new classes, use fields, catch exceptions, or use static constructors.
Additional determinism and format validation requirements are described here: https://academy.stratisplatform.com/Architecture%20Reference/SmartContracts/contracts-in-depth.html
The above is certainly the case for developing Blockchain solutions within a decentralised public blockchain. However, permissioned and private blockchain solutions utilise alternate consensus algorithms allowing for more predictable behaviour. These environments do not require the same level of caution when it comes to ensuring determinism.
That is why there is a DLT instance of the Developer Edition package, to cater for those building an application or solution with a private environment in mind. The DLT instance has the aforementioned limitations removed, allowing for developers to utilise all .NET Core classes and external libraries if they choose.
UTXO-based blockchain, Accounts-based contract interactions
One way the Stratis platform differs from e.g. Ethereum is that it is built on a UTXO-based blockchain. To simplify interactions with contracts, Stratis adds an account abstraction layer and modified wallet behaviour.
The net result is that P2PKH addresses can behave as accounts. You can read more about the account abstraction layer here: https://academy.stratisplatform.com/Architecture%20Reference/SmartContracts/account-abstraction-layer.html
Interacting with contracts using the full node API
Contracts can be interacted with via the HTTP API running on a node. Developers building applications on top of a smart contract will need to use this functionality to integrate their apps with their contracts.
The API exposes methods for creating and broadcasting smart contract transactions to the network, as well as querying contract state.
In the developer edition of Cirrus Core, we’ve modified the full node to dynamically generate an API endpoint for each contract deployed on the network. If you wish, you can use these endpoints within your application as well.
You'll find this referenced on the Stratis Academy within Smart Contract Tutorial 2 - A “Hello World” smart contract: https://academy.stratisplatform.com/Developer%20Resources/SmartContracts/Tutorial2-HelloWorld/hello-world-tutorial-introduction.html
Logs and Receipts
Any time a smart contract transaction is included in a block, nodes will generate a receipt that gives some insight into what happened when that transaction was executed. This should generally be the first thing you check after sending a smart contract transaction.
The receipt includes the following information:
- The hash of the transaction.
- The hash of the block the transaction was included in.
- The height of the block the transaction was included in.
- Whether the transaction was successfully executed.
- The amount of gas that was consumed in executing the transaction.
- The sender of the transaction.
- The contract address that received a method call, OR
- The new contract address created by the transaction, assuming it was successful.
- An error message if the execution failed.
- The return value if execution was successful.
- Logs generated as part of execution.
You can access the receipt of a transaction via the wallet or via the Swagger API, using the `/api/SmartContracts/receipt` endpoint with the transaction hash. It's worth noting this will only be available after the transaction has been included in a block so you generally will need to wait about 10 seconds before you can query this.
You can think of logs within contracts as events that you can raise inside the contract. Outside the contract, you can watch for and search through these events.
Logs are defined as a struct inside contract code and can be output via the SmartContract.Log method. The struct's properties can be decorated with the Indexed attribute, which makes the marked attributes searchable. More on this later.
A good example is the TransferLog event inside StandardToken. This log is output every time there is a transfer of tokens. If you were to check the receipt of a successful call to a StandardToken.Transfer method, it would contain a TransferLog event, as well as the address that was sending the funds, the address receiving the funds, and the amount.
From the contract API, you can also use the /api/SmartContracts/receipt-search endpoint to search through all of the transfer events that have been raised in that contract and can even filter by the indexed fields! In the case of TransferLog, we can find all transfers to or from a certain address, as both the To and From properties were indexed. This approach is particularly useful for building interfaces for smart contracts.
Sample Contracts and Resources
For examples of contracts written in C#, take a look at the official Stratis Smart Contract Sample repository. Also check out the CirrusSmartContracts repository, which contains community contributions of smart contracts for deployment on the Cirrus sidechain.
- Full Node: https://github.com/stratisproject/StratisBitcoinFullNode
- Wallet GUI: https://github.com/stratisproject/StratisCore
- JS Library: https://github.com/stratisproject/bitcore-lib-stratis
- Official samples repo: https://github.com/stratisproject/StratisSmartContractsSamples
- Whitelisted Cirrus contracts: https://github.com/stratisproject/CirrusSmartContracts
- Stratis Smart Contract Challenge: https://stratisplatform.devpost.com/submissions
- Ticketbooth Solution: https://stratisplatform.devpost.com/submissions/135976-ticketbooth
- Sales Deed Registry: https://stratisplatform.devpost.com/submissions/135466-sale-deed-registry
- Passport Agency Office: https://stratisplatform.devpost.com/submissions/135671-passport-agency-office