
Introducing Assets Coloring
Solving Funds Lineage in Ledgers with Semi-Fungibility
Introducing assets coloring support in Numscript to tackle one of the hardest, fundamental core ledgering problems: Hidden funds lineage.
Today, we’re introducing assets coloring support in Numscript to tackle one of the hardest, fundamental core ledgering problems. Consider the following balance sheet:
Assets
| Account | Amount |
|---|---|
banks:jpmc | $100 |
banks:evolve | $100 |
Liabilities
| Account | Amount |
|---|---|
users:1234 | $100 |
users:2345 | $100 |
While assets and liabilities do balance, we can’t use this ledger to answer essential questions, such as:
- How much does JPMC owe to
users:1234? It could be either $100, or $0 in the case that Evolve is the bank we used to store this user’s funds, or even any number in between if their funds are distributed across both banks. - Who are the users that JPMC owes money to?
In order to try and answer these questions, you could go and check the ledger transactions history. Doing so will unfortunately quickly hit an intractable reverse graph traversal problem. Alternatively, one could tediously copy lineage information in secondary channels on transactions. This would however come at the cost of falling out of your ledger guarantees model, as the correlation information you’d write wouldn’t be properly backed by the first-class constraints that you get in the ledger. For readers interested in diving more deeply into this problem, I’ve previously written extensively about it here.
This lack of funds lineage is not a problem if your business is a coffee shop. But if you’re building a fintech — orchestrating the holding and movement of assets belonging to your users —, the fully-fungible balance sheet model will quickly start working against you, looking more like an accidental money laundering operation than a trusted forensic tool for correlating liabilities to their originating assets.
Introducing Assets Coloring in Numscript
Equipping you with the ability to solve this problem was the motivation behind our new Numscript construct — asset coloring. By using the \ literal in the source block of a send statement, you can transmute the statement asset (e.g. USD) into a version of it that encodes additional information, such as the underling holding institution. You can think of this operation as a virtual way of taking a pen of a specific color and making a small mark on a bank note to recognize it later.
Subsequent send statements sourcing funds from accounts having received such encoded assets will then be able to express amounts in abstract USD still, with the Numscript interpreter taking care of resolving precisely what kind USD to use:
// User 1234 deposits $100.00
send [USD/2 100_00] (
source = @world \ "JPMC"
destination = @users:1234
)
// User 2345 deposits $100.00
send [USD/2 100_00] (
source = @world \ "EVOLVE"
destination = @users:2345
)
// User 1234 sends $150.00 to User 2345
send [USD/2 150_00] (
source = {
@users:1234 \ "JPMC"
@users:1234 \ "EVOLVE"
@users:1234 \ "OTHER_BANK"
}
destination = @users:2345
)Now, if we want to ask “how much money does JPMC owe to user:1234?”, we can answer it trivially and with certainty: $100. The ledger can even produce an accurate list of all the users JPMC owes money to, and by what amount, by looking for accounts with a positive credit balance denominated in JPMC-encoded USD.
Going further
Beyond leveraging asset coloring to encode the originating identity of funds and solve the asset-liability correlation problem, you can use assets coloring for other cases that can benefit from semi-fungibility.
Imagine granting a bonus to your users on their first cash deposit, with the caveat that this bonus can only be spent for in-app services and not be withdrawn. Their first transaction might look like this:
vars {
monetary $deposit
string $user_id
account $user = @users:$user_id
}
send $deposit (
source = @world
destination = $user
)
send [USD/2 $100_00] (
source = @marketing:campaigns:signup \ "BONUS"
destination = $user
)Subsequently, a transaction for purchasing an app service might look like this:
vars {
string $user_id
account $user = @users:$user_id
}
// purchase service for $10.00
send [USD/2 10_00] (
source = {
$user \ "BONUS"
$user
}
destination = @app:services:premium_subscription
)While a withdrawal transaction wouldn’t include the BONUS kind of USD as an acceptable source type:
vars {
string $user_id
account $user = @users:$user_id
}
// withdraw all available USD balance
send [USD/2 *] (
source = $user
destination = @payouts:777
)Getting started
Asset coloring is now available in the latest Numscript interpreter through the experimental-asset-colors feature flag, giving you a chance to test it before it becomes enabled by default in a future release.
We encourage you to play with it and check for yourself on the Numscript playground how you can solve some your hardest ledgering problems with it.

