NXTER.ORG

Ardor Contract add-on examples

Jelurida is Developing the Contract Concept

Jelurida continues to hone and further develop their Lightweight add-on contracts concept. In the second week of March, we introduced this in the Nxter Newsletter.  

Lior wrote:

You don’t need to pay gas for these contracts and you can program in Java. On the other hand the “contracts” are only executed by anyone running the addon and it’s not part of the consensus i.e. you can verify that anyone who created a transaction based on the contract did not cheat, but if they cheat or just choose not to run the contract then you cannot fix it. i.e. some trust in the contract executor is required.

Lior continues deploying example contracts to the decentralized data cloud, and we expect to see a number of blog posts from him soon going into detail about the add-ons concept. Until then, here’s the first view, as posted in the #developers channel in ArdorNxt.Slack.com.

 

Hello World 

Lior –

While we continue to develop our contracts concept, you can experiment with it by sending a message transaction, on the Ardor testnet, with text:

{ “chain”: 2, “fullHash”: “53758cc1f44a3eaf86cc187cbd2b73c2a60c0cf60adafb734fc42477bf6d29c2” }

to account ARDOR-NFAY-XYBA-SZ4G-H8SHA

In response, you should receive an automatic greeting message from the HelloWorld contract deployed to cloud data.

The contract code is:

 public void processTransaction(TransactionContext context) {
      if (!context.validateSameRecipient()) {
          return;
      }
      JO transactionJson = context.getTransactionJson();
      int chainId = transactionJson.getInt(“chain”);
      Chain chain = Chain.getChain(chainId);
      String recipientRS = transactionJson.getString(“senderRS”);
      JO params = new JO();
      params.put(“recipient”, recipientRS);
      JO message = new JO();
      message.put(“text”, “Hello ” + recipientRS);
      params.put(“message”, message.toJSONString());
      params.put(“messageIsPrunable”, “true”);
      context.createTransaction(“sendMessage”, chain, params);
  }

The contract transaction is 2:71660bdaa260d790772e3fc64470a8db465f6b395a0e134f921d57d6fd9589f0

The PingPong Lottery

Send any amount in any chain, on the Ardor testnet, with attached message text:

{ “chain”: 2, “fullHash”: “798131112caf0f417abd44eaac64f432d0dac147a0d7021b9232d726e215b4be” }

to account ARDOR-NFAY-XYBA-SZ4G-H8SHA

In response you will receive back amount between 0 and 2x your investment.

Contract code is:

public void processTransaction(TransactionContext context) {
if (!context.validateSameRecipient() || !context.validateTransactionType(PaymentTransactionType.ORDINARY, FxtTransactionType.findTransactionType((byte)-2, (byte)0))) {
return;
}
Random r = context.getRandom();
long amount = context.getAmountNQT();
long returnAmount = BigInteger.valueOf(Math.abs(r.nextLong())).multiply(BigInteger.valueOf(2)).multiply(BigInteger.valueOf(amount)).divide(BigInteger.valueOf(Long.MAX_VALUE)).longValue();
Logger.logInfoMessage(String.format(“amount paid %d amount returned %d”, amount, returnAmount));
Chain chain = context.getChain();
long recipient = context.getSenderId();
JO input = new JO();
input.put(“recipient”, recipient);
input.put(“amountNQT”, returnAmount);
context.createTransaction(“sendMoney”, chain, input);
}

The contract transaction id is, of course, the transaction id we mentioned in our message 2:798131112caf0f417abd44eaac64f432d0dac147a0d7021b9232d726e215b4be

Oracle

Here is an example for an “Oracle” contract.

Send 1 IGNIS or more with attached message:

{ “chain”: 2, “fullHash”: “409c120e6e7551927be4856389bb34cd257ccb84cfb202569327c4a3a89f0e7a” }

to account ARDOR-NFAY-XYBA-SZ4G-H8SHA

In response you will get back a message with the calculated rate of IGNIS per ARDOR from both Bittrex and the Coin Exchange to help you identify arbitrage opportunities.

Contract code:

package nxt.addons.contracts;

import nxt.addons.TransactionContext;
import nxt.blockchain.ChildChain;
import nxt.util.Logger;
import org.json.simple.JSONValue;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class IgnisArdorRates extends AbstractContract {

/**
* Sample contract which receives amount from the trigger transaction and returns a random amount between 0 and twice the received amount
* @param context contract context
*/
@Override
public void processTransaction(TransactionContext context) {
JO response = new JO();
if (!(context.getChain() == ChildChain.IGNIS) || context.getAmountNQT() < ChildChain.IGNIS.ONE_COIN) {
context.setErrorResponse(10001, "Oracle requires a payment of 1 IGNIS to operate");
return;
}
// {"success":true,"message":"","result":{"Bid":0.00003072,"Ask":0.00003098,"Last":0.00003090}}
JO ignisTickerResponse = getRate("IGNIS");
if (ignisTickerResponse.get("errorCode") != null) {
context.setResponse(response);
return;
}
Double ignisLastTrade = ignisTickerResponse.getJo("result").numericToDouble("Last");
JO ardorTickerResponse = getRate("ARDR");
if (ardorTickerResponse.get("errorCode") != null) {
context.setResponse(response);
return;
}
Double ardorLastTrade = ardorTickerResponse.getJo("result").numericToDouble("Last");
long ignisNQTPerARDR = BigDecimal.valueOf(ardorLastTrade).
multiply(BigDecimal.valueOf(ChildChain.IGNIS.ONE_COIN)).
divide(BigDecimal.valueOf(ignisLastTrade), RoundingMode.HALF_EVEN).
longValue();
response.put("BittrexIgnisNQTPerARDR", ignisNQTPerARDR);
JO requestParams = new JO();
requestParams.put("chain", 2);
requestParams.put("exchange", 1);
requestParams.put("firstIndex", 0);
requestParams.put("lastIndex", 1);
JO getCoinExchangeTradesResponse = context.sendRequest("getCoinExchangeTrades", requestParams);
JA trades = getCoinExchangeTradesResponse.getArray("trades");
if (trades.size() > 0) {
JO trade = trades.get(0);
response.put("BlockchainIgnisNQTPerARDR", trade.get("priceNQTPerCoin")); // TODO test with real data
}
JO input = new JO();
input.put("recipient", context.getSenderId());
input.put("message", response.toJSONString());
input.put("messageIsPrunable", true);
context.createTransaction("sendMessage", context.getChain(), input);
}

private JO getRate(String coin) {
HttpURLConnection connection;
JO response = new JO();
String protocol = "https";
String host = "bittrex.com";
int port = 443;
String urlParams = "/api/v1.1/public/getticker?market=BTC-" + coin;
URL url;
try {
url = new URL(protocol, host, port, urlParams);
} catch (MalformedURLException e) {
response.put("errorCode", 10002);
response.put("errorDescription", e.getMessage());
return response;
}
try {
Logger.logDebugMessage("Sending request to server: " + url.toString());
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
try (Reader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"))) {
return new JO(JSONValue.parse(reader));
}
} else {
response.put("errorCode", 10003);
response.put("errorDescription", "No response");
return response;
}
} catch (RuntimeException | IOException e) {
response.put("errorCode", 10004);
response.put("errorDescription", e.getMessage());
return response;
}
}
}

Class file is deployed as cloud data txid 2:409c120e6e7551927be4856389bb34cd257ccb84cfb202569327c4a3a89f0e7a

Note that when you send a message to the contract you always use this txid in the message

ProbertyBasedLottery

And contract 2:ab2ee853bf8bf57b550d16d2ffd1bed087b79eefb8b879f8d22f9ec969960a41 is a new version of the PropertyBasedLottery contract used by Bitswift to determine the winner of their twitter campaign: https://www.nxter.org/nxter-news-april-2018-i/#Bitswift_childchain_thread

UPDATE:

Lior has published a series of articles about Lightweight Contracts on his Medium blog, since this post was written. You should check them: https://medium.com/@lyaffe/lightweight-contracts-articles-49c3032a50da

Follow Lior’s blog on Medium.

What Good is Ignis, Anyway?

Recently there have been several posts on the Nxt and Ardor subreddits asking about Ignis: Why did Jelurida create it? What problems does it solve? Why would people want to use it?

I suspect that for a lot of longtime members of the Nxt community, the answers to these questions are self-evident. For newcomers, though, it’s a fun and helpful exercise to brainstorm interesting applications of the Nxt/Ardor tech. In that spirit, I replied to one of those posts with a few thoughts about what you can do with Ignis. I figured Nxter readers might be interested to hear them, too, so I’m posting them here for you to consider.

So what’s special about Ignis? In a nutshell, Ignis is the only child chain on the Ardor platform that is guaranteed to be permissionless and to support all available features. It will have basically all of the features that Nxt currently has, plus a few new ones (see apenzl’s excellent write-up for a survey of the new functionality). If you’re new to Nxt and Ardor and haven’t spent some time with the full client yet, I’d strongly recommend you do so. It’s quite impressive just how much you can do with the built-in features.

IGNIS

Without further ado, here are a few examples of ways you might use Ignis, most of which apply to Nxt, too.

Co-Ownership of Property

Suppose you and some friends own a rental property. You can create an asset on Ignis to represent shares of the property and distribute the shares among the co-owners. As the property earns money, you can pay dividends to the owners in proportion to the amount of the asset that they hold (this is a built-in feature). They can freely buy or sell their shares in it (another built-in feature), making it easy for them to take on as much or as little risk as they are comfortable with. If you need to make a collective decision, like whether to remodel it, you can conduct a poll of your asset holders (another built-in feature) where their votes are weighted by their share of the asset, or where each person gets an equal vote, your choice.

Decentralized Crowdfunding

Suppose you want to conduct a Kickstarter-like crowdfunding campaign, where your supporters don’t have to pay unless you meet your fundraising goal. The Monetary System on Ignis supports exactly this application, among many others. You can issue your own “currency” (token) to represent a receipt of payment from your backers, set a deadline for the fundraiser, and make the transfer of funds conditional on raising at least some minimum amount of money. All of this is built-in functionality. As your project progresses, you can send your supporters messages using the Messaging System with updates on important milestones. Finally, when your project turns out to be wildly successful, you can pay bonuses to your early backers proportional to their share of your tokens.

Retail

Suppose you own a video game store and Nintendo announces that they’re selling a Nintendo64 Classic. You know that you’ll only receive a limited quantity. To save your customers the hassle of lining up outside your store at 5 am to try to get their hands on one, you decide to offer them an opportunity to buy vouchers ahead of time, which they can exchange at their convenience for the game system. You’re worried that scalpers will buy up all of your vouchers at MSRP and resell them for a huge markup, though.

You decide to issue your voucher through the Ignis Monetary System as a controllable currency. This means that you can sell it at a fixed price and buyers can’t resell it later to anybody but you. When the account holder later visits your store, you buy back the voucher for next-to-nothing and give him or her a Nintendo64 Classic in return.

Fintech

Suppose you want to start a hedge fund like Numerai. You want to issue a token that can only be held or traded by data scientists, whose models you want to collect and evaluate.

You first solicit applications from data scientists through your website and decide whether they’re worthy to participate. The candidates you’d like to enroll send you their Ardor addresses, and you use your account to mark their accounts with a special property indicating that they are eligible to participate. Next, you issue an asset on Ignis using the new Asset Control and Vote by Account Property features, and specify that your asset can only be traded by accounts with the property you used to designate eligibility. You then make payments of your asset to each account proportional to how well the account holder’s models perform, and you pay dividends to all asset holders in proportion to their holdings. The result is that people who submit the best models get the biggest shares of your dividends.

Perhaps you charge your users a fixed quantity of your asset for each model they submit, both to ensure they have some skin in the game and to help redistribute the asset away from the users who submit the worst models. Since Ignis supports sending short messages along with payments, a user could annotate such a payment with an ID number that corresponds to the submitted model, allowing you to easily track which models’ submission fees have been paid.

Venture Capital

Suppose you want to start a crowdfunded venture capital firm. You want to sell shares of your firm to raise money, allow shareholders to vote on which projects to invest in, and pay them dividends in proportion to their holdings. You like the idea of making the investment decision somewhat decentralized, but you’re nervous about using a strict decision-by-majority investment model. As a hedge, you’d like to allow a supermajority of your board members to veto investment decisions made by your investors.

You can issue an asset on Ignis representing shares of your company, then make payments to the companies you invest in using composite phased transactions, another new feature. You can set the phasing conditions to say that each payment succeeds if at least a majority of your asset holders approve of it and less than eight out of your ten board members try to veto it. If these conditions are met, the company gets funded. Otherwise, the transaction does not occur. And how do you elect your board members? Why, the built-in voting system, of course.

Conclusion

These examples barely scratch the surface, but hopefully, they give you an idea of the kinds of things Nxt and Ignis can do.

Note that you can do any of these things using just the standard Ardor wallet. If you’re a programmer, though, and you want to make things a little easier on the people you’re interacting with, you can write an app with a custom interface that interacts with Ignis only on the backend. Your users don’t even necessarily need to know that they’re transacting on a blockchain.

Along those lines, I’d suggest that most of the things you would want to do on Ethereum can also be done on Ignis. As I’ve argued before, writing secure smart contracts on Ethereum generally requires either keeping them very simple or introducing some trust between users and developers. In the former case, Ignis’s smart transactions often substitute directly for smart contracts, and in the latter case, you might as well move most of your code off-chain and only use the blockchain for the parts that really need to be trustless. Either way, I don’t think the extra flexibility that smart contracts offer is quite as big an advantage as it appears to be at first blush.

So if you find yourself wondering what value there is in Ignis, first ask yourself what value there is in Ethereum. For each example application you come up with, try to convince yourself that you absolutely could not use Ignis to accomplish the same goal with a similar degree of decentralization. If you share my concerns about the security of complex smart contracts that are truly immutable, you might be surprised at how similar the potential applications of both platforms are.

Finally, it’s worth mentioning that there might be significant non-technical challenges to a couple of the examples I’ve given. In particular, the U.S. Securities Exchange Commission ruled several months ago that some tokens traded on blockchains can be considered securities, especially in cases where investors have “a reasonable expectation of profits derived from the managerial efforts of others.” In such cases, issuers of those tokens must register with the SEC in order to do business in the U.S. I suspect that this is not as big a deal as a lot of blockchain enthusiasts make it out to be, but that’s probably the subject of a different article. 🙂

In any event, I hope these examples help put into concrete terms just how much functionality Ignis offers. If you can think of other (better?) examples for how to use Ignis, please add them in the comments section! And as always, I’d greatly appreciate constructive criticism.

Ardor vs. the Competition, Pt. 7: Ethereum (Smart Contracts)

This post is part of a series that compares Ardor to other blockchain projects with similar features or goals. You can find the previous posts here:

This week I studied Ethereum, which probably needs no introduction.

For several of the projects I’ve surveyed throughout this series, it has been rather difficult to find detailed, technical information. Ethereum has exactly the opposite problem: there is so much information available that it is difficult to distill it into a reasonable-length article without oversimplifying important ideas.

For this reason, I have chosen only two aspects of Ethereum to compare to Ardor. This installment compares its smart contracts to Ardor’s smart transactions, and the next article will compare the approaches that the two platforms take to managing blockchain bloat. There are many more topics I would have liked to cover–its plans to move to Proof-of-Stake (Casper), its state-channel strategies (Raiden and Plasma), its partnerships with large companies through the Enterprise Ethereum Alliance, and a sampling of the projects running on it, for example–but discussing even a couple of these topics in satisfactory depth is a daunting enough task. Besides, the two topics I chose offer the most interesting comparisons between the two platforms, in my opinion (but see the Ardor vs. Plasma post, linked above, for some thoughts on Plasma).

Without further ado, let’s talk about smart contracts.

Smart Contracts and “Rich Statefulness”

Ethereum’s design combines elements of Bitcoin and Nxt, and adds several novel features. Like Bitcoin, Ethereum uses a low-level scripting language to encode transactions, and it stores the contents of each block in Merkle trees whose root hashes are recorded in the block headers (more on this in the next article). And like Nxt, it tracks the current state of account balances and other account-specific data directly instead of using Bitcoin’s unspent transaction output (UTXO) model.

The most important innovations that Ethereum adds to this mixture are twofold: the ability to store scripts (contracts) in so-called “contract accounts,” which transact autonomously instead of being controlled by a user; and the ability to persist data in an account from one transaction to the next. Ethereum’s scripting language is also somewhat more powerful than Bitcoin’s language, allowing contracts to include loops and to invoke other contracts.

Combining these ideas, it is possible to create stateful “smart contracts,” which are bits of code and data that live in contract accounts and act as autonomous agents, listening for input from users and other contracts and transacting with them according to the rules defined in their contract code. The “stateful” modifier in the previous sentence is crucial: because a smart contract can have its own internal state, it is possible for one transaction to affect how subsequent transactions are processed. This is a significant departure from Bitcoin’s model, where transaction scripts only execute a single time and where the notion of the “state” available to a script is essentially limited to whether a given output is spent or unspent.

(You might have noticed that I haven’t said anything about Turing completeness. Depending on how pedantic you’re feeling, you could argue either side of the question of whether Ethereum’s scripting language is actually Turing complete. As the speaker in this excellent video explains, though, Turing completeness is a bit of a red herring anyway. Much more important is the fact that smart contracts are stateful and can transact with one another and with users in interesting ways.)

The potential applications of smart contracts extend far beyond setting conditions on the transfer of money from one account to another. Even the original white paper (which is a great read, by the way) proposed a handful of non-financial uses, including file storage, voting, distributed computing, governance of decentralized organizations, and decentralized marketplaces. Since then, developers have found plenty of other applications, too, such as decentralized messaging. And of course, the most common application of Ethereum so far, seemingly by an overwhelming margin, has been to conduct token sales for various projects.

Ardor’s “Smart Transactions”

If that list of applications sounds familiar, it might be because all but one of them have already been implemented in Nxt and Ardor as prepackaged “smart transactions.” Pioneered by Ardor’s predecessor, Nxt, smart transactions are bits of “blockchain 2.0” functionality that the Nxt and Ardor developers have made available as part of the protocol itself. They allow developers to create blockchain applications without having to write and test their own smart contracts.

In order to enable ordinary users (i.e., non-developers) to take advantage of this functionality, too, the official Nxt and Ardor wallets include a handful of features built from smart transactions. These include:

  • the Asset Exchange, where users can issue assets, trade them, and pay dividends to asset holders;
  • the Monetary System, where users can issue currencies and conduct several different types of crowdfunding campaigns;
  • a messaging system, which allows users to send each other plain-text or encrypted messages;
  • a voting system, which allows users to conduct polls by account, account balance, asset balance, or currency balance;
  • an integrated coin shuffler, which can afford users a degree of privacy by obscuring their transaction histories;
  • a decentralized data store, which can record the hash of a file permanently on the blockchain and, optionally, record the file itself permanently in special archival nodes;
  • a decentralized marketplace, where users can buy and sell goods and services peer-to-peer;
  • a new Coin Exchange (Ardor only), where users can trade child-chain coins directly for one another; and,
  • a number of advanced features, such as phased transactions, which allow users to set constraints on when and how other transactions are executed, and account properties, which can be used to associate arbitrary data with an account.

These are not the only applications that can be built from smart transactions, of course, but they do illustrate the breadth of what can be achieved with them. All of these features, plus a few more, will be available on Ignis, Ardor’s first child chain. Creators of other child chains will have the option to implement as many of these features as needed to suit their projects.

I’ve heard several analogies to describe smart transactions, but my favorite is that they are like Legos, while smart contracts are like clay: the former don’t provide the same degree of control over the finer details, but they are quicker and easier to use than the latter, and can still be combined to form some quite impressive final products.

The analogy isn’t perfect, of course. A strong argument for smart contracts is that it is possible for potentially all of the business logic of a decentralized application (Dapp) to be recorded permanently and immutably on the blockchain, for example, whereas a Dapp built from a combination of smart transactions likely includes some external code. In the latter case, using the Dapp might require some degree of trust in the developer not to change the rules in later versions of it.

Viewed from another angle, though, this comparison hints at arguably the biggest drawback of smart contracts: the ease with which they allow programmers to make multimillion-dollar mistakes that cannot be corrected.

Security Considerations

Just about all software that is even modestly complex contains flaws, and too often these flaws make the software vulnerable to exploitation by an attacker. Smart contract developers face a particularly difficult task because the code they write is immutable, and as a result its vulnerabilities are permanent.

Unfortunately, catastrophic failures of buggy smart contracts have not been rare. The attack that froze $150 M worth of ether stored in multisig Parity wallets and the $30 M hack of that same wallet several months prior are the most recent examples to grab headlines, but they are not the first and almost certainly not the last. For an overview of some common vulnerabilities and analysis of several real attacks, including the infamous DAO hack, I strongly recommend this excellent paper by three researchers from the University of Cagliari.

It is worth noting that the Ethereum protocol and the Ethereum Virtual Machine (EVM) were not responsible for any of these attacks. Ethereum’s supporters sometimes point this out, arguing that Ethereum itself is quite secure, and all that is needed is for developers to write better smart contracts. In a literal sense they’re right, of course: in all cases, Ethereum did what it was supposed to do, and ultimately the blame lies with smart contract developers.

But personally, I wonder whether this assessment is too quick to absolve Ethereum, and whether the problem might run a bit deeper than just a few buggy smart contracts. For now, anyway, it seems to me that Ethereum’s fundamental predicament is that it gives programmers tremendous power, but insufficient tools to use that power safely.

Developers’ ambitions almost always exceed the level of complexity that they can achieve while keeping their code perfectly bug-free, and there will therefore be a constant temptation to make functionality a higher priority than security (this is nearly universal in software development, by the way). Immortalizing the buggy code that they produce by storing it in the blockchain, Ethereum brutally and mercilessly holds them to account for their sins.

Thankfully, there are certainly ways to mitigate the risk of writing vulnerable smart contracts. For example, it is possible to design a smart contract that can be updated by having it delegate its responsibilities to a second contract, commonly called a “library contract,” at an address that can be changed to point to a different library contract later.

This approach allows developers to patch vulnerabilities, but as a consequence, it introduces the thorny question of who is allowed to switch to a new library contract. If it is a single third-party account, then the design reintroduces some degree of trust between that account and users. On the other hand, if the developers take another approach, such as allowing a majority of users to vote in order to approve each new library contract, then there are potentially further problems to solve, such as writing a secure voting mechanism, making sure that users are sufficiently informed and engaged to vote, and preventing an attacker from doing significant damage in the time it takes to organize a vote.

Another very promising approach towards securing smart contracts is to use techniques of formal verification borrowed from mathematics. I do not know much about formal methods, so please take what I write here with a grain of salt, but I do know that it is easiest (or indeed, feasible at all) with simple programs whose proper functioning can be expressed as a set of short, simple rules. In such cases, it can be possible to prove with certainty that the program contains no bugs. Even straightforward techniques like looping and recursion can complicate the analysis significantly, though, so it is best if the program under test is as simple as possible.

Why am I droning on and on about all this? Putting these thoughts together, it would seem that the best way to write smart contracts might involve: 1) keeping them as short and as simple as possible; 2) delegating the core business logic to library contracts that can be updated if necessary; and 3) reusing libraries that have been thoroughly vetted, so as to keep the amount of new code to a minimum. If the second of these points requires that users trust the contract’s author to some degree, as is often the case, then contracts designed according to these three guidelines start to look a lot like Ardor’s smart transactions: bits of stable, thoroughly tested code that expose the most commonly needed functionality, which developers can assemble into more complex programs.

Trade-offs between Security and Flexibility

I am not suggesting that Ardor’s smart transactions can accomplish all of what Ethereum’s smart contracts can securely accomplish, nor am I even arguing that combinations of smart transactions can always emulate smart contracts. What I am saying, though, is that I think there is a natural tension between the flexibility that a platform offers and the security of the code that developers inevitably write for it.

In this view, blockchain platforms can be located on a security-flexibility continuum. Near the “security” extreme is Bitcoin, whose scripting language is deliberately quite limited in order to prevent users from locking their coins with vulnerable scripts (though this is still possible, of course). Nxt and Ardor occupy a position somewhere toward the middle of the spectrum, limiting developers to a set of predefined transaction types but including an awful lot of functionality in those types.

Ethereum’s smart contracts, on the other hand, occupy the entire spectrum. It is possible to write extremely simple, trivially secure scripts on Ethereum, and it is also possible to write more complicated scripts that contain very subtle vulnerabilities. Perhaps just as importantly, it is difficult for users to tell the difference between these cases–and unreasonable, in any event, to expect them to try. Using Ethereum safely necessarily means avoiding the “flexibility” end of the spectrum, even if it comes at the cost of introducing some extra trust between users and developers.

Finally, it is worth mentioning that Ardor offers a new feature, not previously available in Nxt, that helps it inch towards the “flexibility” end of the continuum: the ability to combine phasing conditions using Boolean AND, OR, and NOT operators to achieve primitive smart-contract-like behavior.

Briefly, phased transactions allow users to condition an underlying transaction on some event, such as approval by a certain number of specific accounts (m-of-n multisig), a vote by accounts holding a particular asset, the expiration of some amount of time (timelock), or the revelation of a secret (e.g., a hashlock). On Ardor, combinations of these phasing types can encode more complex conditions, such as, “transaction X is valid if a majority of ABC Corp.’s asset holders approve of it by date Y, unless it is vetoed by a supermajority of ABC Corp.’s board members.”

It will no doubt be possible to combine phasing conditions in ways that allow for unexpected outcomes, possibly including theft or loss of funds. But the advantage over smart contracts in terms of security is still there, I would argue, since developers can focus on making sure the business logic of the transaction is sound, without having to worry about low-level bugs like race conditions. And of course, the drawback of offering less flexibility than a smart contract is still there, too.

Conclusion

With a protocol defined by a set of prepackaged smart transactions instead of a low-level scripting language, Ardor will probably never be able to offer developers as wide a range of possibilities as Ethereum does, at least in cases where everything must be done on-chain for minimal trust between parties. On the other hand, writing nontrivial contracts that follow security best practices might well require additional trust between users and developers anyway. And of course, Ethereum users ultimately have to trust the authors of smart contracts not to have made any mistakes and to have duly scrutinized and tested their code in order to make sure of it.

Naturally, you might say the same thing about any software, including Ardor’s smart transactions, but there is a key difference: there is simply so much more code running on Ethereum. Nxt has been open-source since its inception, providing ample opportunity for peer review, and Ardor’s code, which builds on the Nxt codebase, will be opened soon. Moreover, each new change to the protocol has been vetted thoroughly on a public testnet before being officially released. The same ought to be true of each and every smart contract, but with so much code being written, it seems like there are inevitably more opportunities for bugs to slip through into production.

In any event, I suspect that the degree to which most successful Dapps will rely on immutable code is still an open question. If access to an immutable database and a handful of simple operations on that data are sufficient for most applications, then Ardor’s smart transactions seem to me to have an obvious advantage over smart contracts. If, in contrast, the notion that “code is law” turns out to be essential to the viability of most Dapps, with each Dapp requiring most of its unique code to be recorded on the blockchain in order to be truly trustless, then Ethereum’s approach is probably superior.

I expect that there will be real-world applications that suit each platform. But I also wonder whether it will eventually become clear that one of the two approaches best handles a sizable majority of applications. Which approach will ultimately “win” is not at all clear to me, but I suspect that the deciding factor will be users’ judgments of the degree of trust that each case requires. And since the entire appeal of blockchain technology is that it allows users to transact with minimal trust, I’d say that outcome would be quite appropriate.

Thanks for reading! If you enjoyed this article, be sure to read the next part of the series, which compares the ways that Ardor and Ethereum cope with blockchain bloat.


Try Ardor on testnet

About the latest Ardor testnet version