An Intro to Nebulas for Ethereum Smart Contract Developers
Nebulas is yet another platform on which you can develop smart contracts. It offers a means of using JavaScript to develop Smart Contracts – an intriguing alternative to more established solutions, such as Ethereum.
I read about it for the first time on Reddit when they announced the Nebulas Incentive Program, which rewards developers for successfully submitting a dApp (decentralised application). From Nebulas’ whitepaper, we can learn about the team’s motivation and their goal to come up with a search engine and ranking algorithm for dApps. Sounds familiar? Let me google that. Oh, that sounds like Google.
By skimming through the whitepaper, you learn that Nebulas recognizes the problem of “measurement of value for applications on the blockchain” and the difficulties of platforms that operate on blockchain to upgrade themselves and evolve.
This is not a review, and I neither want to nor feel knowledgeable enough to assess whether such the problems that this project solves, as mentioned above, are worth investing your time or money. I am interested in the developer experience, the quality of the provided tooling from an engineering perspective and seeing how it compares to the well-established Ethereum. If our goals are inline, then this is a post worth reading.
Ethereum Virtual Machine and Nebulas Virtual Machine
In general, learning about the Nebulas Virtual Machine (NVM) and how the platform works is a breeze if you are familiar with how Ethereum works. Supplied gas intrinsically binds computation on both the Ethereum Virtual Machine (EVM) and NVM. The transaction fee is the the gas used, multiplied by the gas price.
There are two types of accounts: external/non-contract account and smart contracts (denoted accordingly by type 87 and 88).
Calls running locally on a currently connected node are free, immediately return values and do not change the blockchain state.
Each transaction costs gas and changes the blockchain state (it’s dirt cheap and a small fraction of a penny at the time of writing).
The most noticeable difference is the programming language used to develop smart contracts. On EVM, Solidity is the de facto standard language to write a smart contract. In its current form, NVM supports JavaScript (v8 6.2, from what I have found out) and quasi-TypeScript though compilation to JS. There are no typings available for storage, transaction or other globally available objects.
Due to plans for supporting LLVM, we might see the broader range of supported languages, such as C/C++, Go, Solidity or Haskell. This would be quite a feature if the Nebulas team can deliver on this promise and a big disappointment otherwise.
Smart Contracts
Let’s take a deep dive into how the same constructs are implemented in Ethereum (Solidity) and Nebulas (JavaScript).
Transfering Value
Both Ethereum and Nebulas have the smallest nominal value called Wei. 1 ETH or 1 NAS is 10^18 Wei. The value accepted by the transfer function should be the number of Wei. In the case of Ethereum, it is uint256, and for Nebulas, it should be an instance of BigNumber.
Transaction Properties
Transaction properties exist in the global namespace and provide a set of information about the height of the chain, block timestamp, supplied gas and much more.
Ethereum address validation is possible using mixed-case checksum encoding, as described in EIP55, the proposal by Vitalik Buterin. Wallet software has widely adopted this improvement. Due to using a 20-bytes address type, it is impossible to validate it using this method on-chain. Nebulas address is a little different; you can calculate the checksum from the public key. It also contains the information regarding whether the address is a regular account or a smart contract.
Preventing Overflows
The maximum safe integer in JavaScript is 2^53 – 1. The maximum safe integer (unsigned) in Solidity is even bigger: 2^256 – 1. In some particular use cases, it is possible to overflow (or underflow) these values. To mitigate the severity of any issues that may originate from an overflow, you can use third-party libraries.
In Solidity, you can use the popular SafeMath library, which throws error, consuming all the gas left in case of the underflow or overflow.
Our JavaScript-powered smart contract running on Nebulas can use bignumber.js without any additional imports.
Contract Structure
Solidity is a contact-oriented language. This means that it is an object-oriented language with a contract keyword that defines a class-like type, able to store state and provide behavior for this state via functions.
Furthermore, Solidity also supports interfaces and Python-like multiple inheritance (through C3 superclass linearization).
On Nebulas, a contract is a class (or a function) with methods available on its prototype. One function, init, is required and executed during the contract initialization; it accepts arguments passed during the contract creation.
State Variables
Solidity has three types of storage if you do not count the events log as a fourth: Storage, Memory, and Stack. Storage keeps contract state variables.
Nebulas provides the abstraction on top of its storage capabilities. Using LocalContractStorage, we have to indicate which variables should persist explicitly.
Visibility
Solidity has four visibility specifiers: public, private, external and internal. The public specifier allows for external and internal calls, while private functions can be called only from the contract that defines them. Internal functions work like private, but extending contracts can call them too. External functions are callable by other contracts and transactions, as well as internally using “this” keyword.
On Nebulas, private functions are achieved via naming convention and not forced by the language. All functions that start with an underscore are not a part of the interface and cannot be called via transaction.
Client-Side Applications
Ethereum dApps use an injected web3 instance with the embedded provider that asks users for confirmation each time the dApp tries to sign the transaction. MetaMask, which is an Ethereum extension for your browser, supports this flow, as well as Mist and Status (wallet apps with dApps browsers for desktop and mobile, accordingly).
When using Nebulas dApps, you can install WebExtensionWallet. It lacks convenient web3 abstraction but it is good enough for PoCs and simple use cases. The API for sending transactions is very similar to using RPC directly. In fact, using RPC directly is the easiest way to make a call that does not require signing.
Deployment
There are multiple ways to deploy contracts in Ethereum. The most developer-friendly are Remix and Truffle migrations scripts. Nebulas provides Mist-like experience within its web-wallet. You copy and paste the contract source code, specify constructor arguments and you are all set to go.
Alternatively, you can change the contract source to an escaped string and send the transaction, which creates a new contract using RPC.
Testing
Testing is one of the most crucial parts of smart contracts development, due to their immutability and costly mistakes. The Nebulas ecosystem is in its infancy and has no tooling to make such testing possible. Although clumsy, it is not impossible to test the Nebulas smart contract. It requires mocking internal APIs but, once you set your mind to do it, you will more or less reliably test the contract.
It is much easier to test smart contracts in Solidity. Thanks to the efforts of the Truffle’s team, you can almost reliably test contracts in isolation in both Solidity and JavaScript.
Conclusion
Frankly, since mid-2017, I thought that Lisk was going to be the first platform for JavaScript smart contracts. Nebulas took me by surprise.
Nebulas, of course, cannot match the more mature Ethereum ecosystem yet but the comparison to come up with what is better is not the goal here. I think that new projects should be a little more modest and be upfront about their shortcomings. My initial disappointment was only due to the huge claims made at the time.
When I take a step back, it is clear that the Nebulas team have made the considerable progress in the last few months. I believe that this is a project worth observing and I hope that releasing mainnet was not premature and is not going to slow down the development as it tends to with other, similar projects.