Usually colored coins are described as a simple asset transfer/ownership tracking system which lacks capabilities for "smart contracts". (Aside from those which are based on Bitcoin scripting and transactions, i.e. this
https://en.bitcoin.it/wiki/Contracts .)
This is largely true, as the colored coins model is limited compared to what metacoins (Mastercoin, Counterparty) or systems like Ethereum can provide: it lacks an ability to use implicit dependencies when computing color values, and implicit dependencies are crucial for implementation of derivatives, betting, etc.
(I.e. the value of a coin must depend on something which is outside of that specific coin's history.)
(It's not necessarily a bad thing: one could argue that simplicity makes colored coins more suitable for simple asset transfer/ownership tracking systems.)
However, this doesn't mean that one must ditch the colored coins model to implement complex smart contracts. There is also an option to build a hybrid system where colored coins exist as one of layers, and extra "business logic" is added on top of it. Quite likely such a hybrid system will require non-fungible colored coins with non-scalar colorvalue types.
I described non-scalar colorvalue types in the follow-up discussion to "The theory of colored coins" article: the model described in the article doesn't require colorvalues to be of a particular type, thus it can be a tuple, vector, or, really anything. I provided several examples, most interested and advanced of which was fully decentralized prediction market.
However, these examples were provided as sketches and ideas and lacked formalized, rigorous descriptions.
So this is the problem: we lack formalisms which are necessary to described advanced used of colored coins.
The concept of functional colored coins, which I'm going to introduce in this article, is one of such formalisms.
(I'm aware of another such formalism which is currently in advanced stages of development, but I can't elaborate on this.)
We will start with a motivating example: CFD/NDF-style derivatives. Formal description will be provided after this example.
Color kernels which are in use now (OpenAssets, EPOBC) work with colorvalues which are concrete numbers. E.g. if we have a USD-denominated e-money based on colored coins, one might have an output with value of $12.45 USD, and he is able to send it to somebody, or split it into several outputs, etc.
But what if instead of concrete numbers we had colorvalues which are ...functions?
We still can represent a concrete number as a nullary function: f() = $12.45
But then we will also be able to create contracts with payoff defined as a function accepting some (external) data as a parameter.
Suppose Alice and Bob have $1000 worth of USDcc each, and they wish to enter a CFD-like contract for MSFT shares. Alice is long on MSFT price, and Bob is short.
Initially they own outputs which have concrete value, thus they can be represented as nullary functions:
Alice_output_1() = 1000
Bob_output_1() = 1000
If the current MSFT price is 48.14, and Alice is long on 10 MSFT shares, her CFD payoff is:
Alice_payoff1(MSFT_price) = (MSFT_price - 48.14) * 10
and Bob's payoff has same absolute value as Alice's payoff, but a different sign:
Bob_payoff1(MSFT_price) = (48.14 - MSFT_price) * 10
They will provide outputs they initially own as collateral (initial margin) of the contract, and after those outputs are used, their payoff can be described by formulas:
Alice_payoff2(MSFT_price) = 1000+(MSFT_price - 48.14) * 10
Bob_payoff2(MSFT_price) = 1000+(48.14 - MSFT_price) * 10
However, as there are no margin calls in this system (we want it to be trustless), payoff must not be lower than 0 or exceed 2000.
Thus, finally we have:
Alice_capped_payoff(MSFT_price) = min(max(1000+(MSFT_price - 48.14) * 10, 2000), 0)
Bob_capped_payoff(MSFT_price) = min(max(1000+(48.14 - MSFT_price) * 10, 2000), 0)
So this looks good enough, as law of conservation is satisfied, thus we can use these formulas to describe values of outputs of CFD transaction.
That is, to create a CFD contract, Alice and Bob will create transaction with two inputs:
Alice_input() = 1000
Bob_input() = 1000
And two outputs:
Alice_output_2(MSFT_price) = min(max(1000+(MSFT_price - 48.14) * 10, 2000), 0)
Bob_output_2(MSFT_price) = min(max(1000+(48.14 - MSFT_price) * 10, 2000), 0)
Sum of inputs is 2000, and sum of outputs is 2000 for all values of MSFT_price, thus this transaction is valid w.r.t. laws of conservation.
As a result of this transaction, Alice owns an output which is worth `min(max(1000+(MSFT_price - 48.14) * 10, 2000), 0)`.
Now what? What can we do with outputs whose colorvalues are non-nullary functions?
First of all, we can combine them back. E.g. suppose after some time MSFT_price goes to $52.14.
If both Alice and Bob have consensus over MSFT_price and no longer want to hold a CFD, they can create a transaction which cancels it:
Inputs:
Alice_input(MSFT_price) = min(max(1000+(MSFT_price - 48.14) * 10, 2000), 0)
Bob_input(MSFT_price) = min(max(1000+(48.14 - MSFT_price) * 10, 2000), 0)
Outputs:
Alice_output_3() = 1040
Bob_output_3() = 960
This can be proven to be a valid transaction, as the sum of inputs is $2000 and sum of outputs is $2000 too.
In a different situation, if Alice no longer wants to be long on MSFT, she might sell her output to Claire for $1040:
Inputs:
Alice_input(MSFT_price) = min(max(1000+(MSFT_price - 48.14) * 10, 2000), 0)
Claire_input() = 1040
Outputs:
Alice_output_3() = 1040
Claire_output() = min(max(1000+(MSFT_price - 48.14) * 10, 2000), 0)
And then Claire will be able to combine her output with Bob's to get actual money.
So far so good. But what if Bob have lost his private key, is Alice (or a person Alice sold her output to) doomed to hold this CFD forever?
What if she wants to redeem her output for actual USD, but Bob is unwilling, or cannot help to cancel the MSFT exposure?
In this case we need CFD-like contract which will expire at some point. Which makes it the same as Non-deliverable Forward (NDF) contract.
Let's replace MSFT_price with MSFT_price_at_T in the original formula: it will denote MSFT price at some concrete point in future (T).
After this point, users might reach a consensus of what MSFT_price_at_T is, and thus it becomes a constant.
Thus expression `min(max(1000+(MSFT_price_at_T - 48.14) * 10, 2000), 0)`
s also a constant, and thus Alice now has a concrete amount of coins, and this can be recognized by anyone who is in a consensus with Alice over what is the value of MSFT_price_at_T is.
So let's say Alice an Bob specified that MSFT_price_at_T is the closing price of MSFT on NASDAQ on 2015-06-07.
Suppose that the closing price of MSFT on NASDAQ on 2015-06-07 is $52.14, as reported by NASDAQ.
Thus after this date, all clients which are able to fetch this number from NASDAQ will see the value of Alice's output as $1040.
Particularly, the issuer will see it as $1040, thus he will agree it redeem it for $1040 according to the issuance contract.
Note that this requires consensus over data which is provided by an external source (NASDAQ), and this cannot be taken for granted.
Thus we have a hybrid consensus system, which combines several different consensus mechanisms:
1. there is a strong cryptographic consensus over the colorvalue-function of Alice's output
2. there is a Bitcoin blockchain-based consensus over who currently owns that output
3. there is a trust-based consensus over the variables which are used in the function
I think it's obvious that this hybrid system has benefits over centralized trust-based systems: we only need to trust a data feed, and only to a limited extent.
A data feed doesn't have a power to block anyone's transactions, or charge fees, or discriminate different agents.
A big part of the system is fully decentralized (as decentralized as Bitcoin), and thus has all the benefits of a decentralized system:
We do not have a single point of failure (if data feed is temporarily down, transaction can still be made, that will only delay "settlements").
If the data feed goes down, clients might elect another data feed, they just need a consensus over what data feed to use.
Finally, if a data feed becomes malicious (publishes wrong data, or a different data to different actors), clients might choose to elect a different data feed.
As settlements are not recorded in the blockchain, but are a function of the current consensus, the situation can be remedied even after a data feed publishes erroneous data: clients can undo the damage as soon as they discover the error and switch to the correct data. Thus the system can be robust to a very large degree.
It's also worth noting that we can use arbitrary consensus mechanisms on the third layer, not just simple trust-based ones.
E.g. there might be a network of trusted oracles which will make sure that everyone has the same view over what data was published.
Or there might be some kind of a Byzantine Fault Tolerant network, or a network based on a Ripple-style consensus.
At this point we are only describing a framework within which different consensus mechanism can be combined.
(A blockchain-based consensus is possible too, e.g. client might scan the blockchain for the executed trades to find the price which is used for CFD/NDF settlements, and thus achieve functionality similar to that of Counterparty.)
Let's summarize what we've got so far:
1. We introduced a level of indirection: instead of getting a monetary value of an output directly, we get a function which yields a monetary value once the data is provided.
2. A color kernel might work with functions instead of scalar values: it will receive input colorvalue-functions and will transform them into output colorvalue-functions according to the data embedded into the transaction.
3. In order to achieve a global law of conservation (we do not want issuer's liability to depend on the contracts which are created by users among each other, i.e. users shouldn't be able to create more money for themselves), it is enough to ensure that the law of conservation is enforced by the color kernel, i.e. it checks that the value of output colorvalue-functions equals to value of input colorvalue-functions for all values of free variables.
4. We get to the actual monetary values using a secondary consensus system, which can be arbitrary: based on trust, BFT-systems, blockchain-based, etc.
One thing which is lacking is a graceful handling of situations in which the secondary consensus is lacking: we do not want the system to blow up in such situations. Instead, we want to detect them, and to pause operations until the consensus is restored.
This can be done using interactive payment protocols/interactive payment verification.