- 1. Introduction
- 2. Specification Update Process
- 3. Architectural Overview
- 4. The Omni Crowdsale: Initial Token Distribution
- 5. Development Omni Distribution
- 6. Embedding Omni Transactions in the Blockchain
- 7. Transaction Definitions
- 8. Handling Blockchain Reorganizations
- 9. Fees
- 10. Unlocking New Features
- Glossary
- Bibliography
- Appendix A: Relevant Omni History
- Appendix B: Regulatory and Legal Compliance - Know Your Jurisdiction
- Appendix C: Financial Disclaimer
- Appendix D: Webservice verification API
- Appendix E: Understanding the cost of Omni protocol messages
-
JR Willett (https://github.com/dacoinminster and jr DOT willett AT gmail DOT com)
-
Maran Hidskes (https://github.com/maran)
-
David Johnston (https://github.com/DavidJohnstonCEO)
-
Ron Gross (https://github.com/ripper234)
-
Marv Schneider (https://github.com/marv-engine)
-
Zathras
-
Dexx (https://github.com/dexX7)
-
Sean Gilligan (https://github.com/msgilligan)
With input by Peter Todd (https://github.com/petertodd)
Note
|
This is the work-in-progress Version 0.7 of the Omni Specification. We are restructuring and reformatting the specification to make it more accessible. The previous version of the specification is in OmniSpecification-v0.6.adoc. |
This document specifies the behavior of the Omni Protocol as implemented in the Omni Core node software.
This introduction will introduce the Omni Layer and Omni Protocol and explain the purpose of the specification and its relationship to the Omni Core client and other implementing software.
We are currently restructuring and reformatting the specification. This process is occurring on Github. See the README for details on how to participate.
General changes or improvements to the specification (such as fixing errors, improving clarity, etc.) are requested and managed using Github Issue and Pull Requests. See the Github README for details.
We are initiating the Omni Layer Enhancement Proposal (OLE) process for adding new features to the protocol as well as for specifying Omni ecosystem functionality above the layer of the Omni Protocol. To participate in the OLE process visit the OLE directory of the Omni Documentation repository on Github.
This section will provide an overview of the Omni Layer and how it interacts with the Bitcoin network and blockchain. It will explain core concepts like the fact that the Bitcoin network will accept and record invalid Omni transactions and that Omni transactions must be validated (or invalidated and ignored) by the Omni consensus engine in Omni Core.
- NOTE
-
This section is forthcoming.
Perhaps you have heard of the “Genesis Block” which launched the Bitcoin protocol. The Omni Protocol has a similar starting point in the block chain, called the “Exodus Address” - the bitcoin address from which the first OMNI were generated during the month of August 2013. The Exodus Address is: 1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P
Initial distribution of Omni was essentially a kickstarter-style period to provide funding to pay developers to write the software which fully implements the protocol. The distribution was very simple, and proceeded as follows:
-
Anyone who sent bitcoins to the Exodus Address before August 31st, 2013 was recognized by the protocol as owning 100x that number of OMNI. For instance, if I sent 100 bitcoins to the Exodus Address before August 31st, my bitcoin address owned 10,000 OMNI after August 31st.
-
Early buyers got additional OMNI. In order to encourage adoption momentum, buyers got an additional 10% bonus OMNI if they made their purchase a week before the deadline, 20% extra if they purchased two weeks early, and so on, including partial weeks. Thus, if I sent 100 bitcoins to the Exodus address 1.5 weeks before August 31st, the protocol recognized my bitcoin address as owning 11,500 OMNI (10000 + 15% bonus).
-
Attempts to send funds to the Exodus Address on or after September 1st 2013 (after block #255365) were not considered OMNI purchases, and were refunded to the sender.
In the event that a purchase had multiple inputs, the input address contributing the most funds was recognized as owning the OMNI.
Note that anyone who purchased OMNI also received the same number of “Test OMNI” which are being used for testing new features before they are available for use in the Omni Protocol.
Initially, the only valid Omni transaction was a “simple send” (defined later in this document), but the additional features described in this document are being implemented, and can be used once they are fully tested.
-
Generation Rate: For every 10 OMNI sold during the Exodus period, 1 additional “Dev OMNI” was also generated, which are being awarded to the Exodus Address slowly over the years following the exodus period (these Dev OMNI are interoperable and fungible with regular OMNI). These Development OMNI will ensure that developers have a continuing incentive to maintain, improve and add features to the Omni Protocol implementations desired by users. The Distribution of these Dev OMNI is structured so that developers receive 50% of the Dev OMNI by one year after the initial Exodus Address period closed (date the Exodus Address closed - August 31st 2013, although transactions up till block 255365 were still accepted to account for slower propagation of transactions still sent on the 31st of August), 75% by a year later, 87.5% by a year later, and so on:
-
As Dev OMNI vest, 50% of them are sent out as bonuses to people who won Omni bounties, in proportion to how much bounty money they won (bitcoins). The other 50% are used for expenses such as retention bonuses. Eventually, the Omni Foundation will turn over all remaining funds to a distributed bounty system, with the Omni Protocol paying its own bounties via a proof-of-stake voting system, and the Omni Foundation will no longer need to administer any funds for the project.
Technical notes:
-
Any Omni Protocol implementation implementing Exodus balance must recalculate the Development Omni amount on each new block found and use the block timestamp for y.
-
When calculating the years since the Omni crowdsale we assume a year is 31556926 seconds.
-
1377993874 is the Unix timestamp used to define the end-date of Exodus and thus the start date for the Development OMNI vesting.
-
Current implementations do not have Test OMNI which vest alongside dev OMNI, but such coins may be recognized at some point in the future if it is deemed desirable.
Bitcoin has some little-known advanced features (such as scripting) which many people imagine will enable it to perform fancy new tricks someday. The Omni Protocol uses exactly NONE of those advanced features, because support for them is not guaranteed in the future, and the Omni Protocol doesn’t need them to embed data in the blockchain.
The Omni Protocol was originally specified to embed data in the blockchain using fake bitcoin addresses (Class A transactions), upgraded to a more blockchain-friendly method which embeds data in a bitcoin multi-signature transaction (Class B), and currently embeds data using the OP_RETURN opcode (for most transactions) making most Omni Protocol data completely prune-able (Class C).
Class C transactions are most preferred due to the Provably Prune-able Outputs avoiding issues of “bloat” and “pollution” of the block chain.
For the purposes of a simplified overview, parties wishing to develop Omni software should support the decoding of Class A, Class B, and Class C transactions, but only need to support encoding of Class C transactions (and certain large transactions may still require encoding as Class B.)
All three transaction classes have (at least) the following three elements in common:
-
A sending Bitcoin address
-
A recipient or reference address (for transactions that require it)
-
A transaction payload: the Transaction Definition (see section 8, Transaction Definitions) that varies with each transaction type. (In this specification, payload is often referred to as "the transaction data", but in future drafts the word payload will be used more consistently.)
The major difference between Class A, B, and C transactions is where/how the transaction payload is stored:
-
Class A — payload stored in fake Bitcoin address
-
Class B — payload stored in redeemable multisignature output
-
Class C — payload stored in OP_RETURN output
Class A and Class B transactions have some unused “padding” bytes at the end of most messages. Those bytes are undefined (they are ignored, so they can have any value).
Not every bitcoin wallet lets you choose which address bitcoins come from when you make a payment, and Omni transactions must all come from the address which holds the Omni currency being used. If a Bitcoin wallet contains bitcoins stored in multiple addresses, the user (or Omni Protocol software) must first ensure that the address which is going to send the Omni transaction has sufficient balance in bitcoins to create the transaction. Then, the Omni-related transaction can be sent successfully from that address.
Wallets which do not allow you to consolidate to one address and send from that address (such as online web wallet providers) will not work for Omni unless they are modified to do so. For this reason, attempting to purchase Omni or Omni currency from an online web wallet will likely result in the permanent loss of those coins.
Other than for these hosted wallets, a Bitcoin address can also be treated as an Omni address, capable of storing and using any Omni Protocol currency.
The section describes the binary format of an Omni transaction, independent of how it is encoded into a Bitcoin transaction. Some fields are optional.
Occasionally it seems prudent to change the format or interpretation of a Omni Protocol message in order to improve the feature or fix a bug. To that end, each message has a version number. All Omni Protocol implementations are expected to keep pace with changes of this nature, but in the event one falls behind, it must treat addresses which broadcast messages using version numbers it does not recognize as “black holes”. That is, any funds or properties which enter the control of that address are considered lost and unspendable, since that address is using a newer version of the Omni Protocol. In the event that the out-dated implementation is upgraded to recognize the new message formats, the blockchain can be re-parsed, and nothing will be lost.
This approach allows old versions of the Omni Protocol to continue operating using the transactions they recognize without trying to parse messages of unknown meaning.
Generally, an out-dated parsing engine should either be upgraded to rejoin consensus, or retired by the owner. Implementations which are not in consensus can be used to attempt to defraud people
This section defines the fields that are used to construct transaction messages.
-
Description: the currency used in the transaction
-
Size: 32-bit unsigned integer, 4 bytes
-
Inter-dependencies: Ecosystem
-
Valid values:
-
1 and 3 to 2,147,483,647 in the real OMNI ecosystem (2,147,483,646 unique values)
-
1 = OMNI
-
-
2 and 2,147,483,651 to 4,294,967,295 in the Test OMNI ecosystem (Test OMNI currencies and properties have the most significant bit set, values start with 0x80000003, yielding 2,147,483,646 unique values)
-
2 = Test OMNI
-
-
-
Description: Specifies whether a smart property is traded against test OMNI or real OMNI
-
Size: 8-bit unsigned integer, 1 byte
-
Inter-dependencies: Currency Identifier
-
Valid values: 1 for OMNI, 2 for Test OMNI
-
Description: used as a multiplier or in other calculations
-
Size: 64-bit unsigned integer, 8 bytes
-
Valid values: 0 to 9,223,372,036,854,775,807
-
Description: used as a multiplier or in other calculations
-
Size: 32-bit unsigned integer, 4 bytes
-
Valid values: 0 to 4,294,967,295
-
Description: used as a multiplier or in other calculations
-
Size: 8-bit unsigned integer, 1 byte
-
Valid values: 0 to 255
-
Description: used as a multiplier or in other calculations
-
Size: 16-bit unsigned integer, 2 bytes
-
Valid values: 0 to 65535
-
Description: the unique identifier assigned to each sale listing an a per address basis
-
Size: 32-bit unsigned integer, 4 bytes
-
Valid values: 0 to 4,294,967,295
-
Description: the 21 bytes needed to uniquely identify a bitcoin address (checksum removed)
-
Size: 21 bytes, binary data
-
Valid values: any 21 bytes (version + output of RIPEMD-160 hash step of creating a bitcoin address)
-
Description: Specifies the number of coins or tokens affected by the transaction this field appears in, as follows:
-
for divisible coins or tokens, the value in this field is to be divided by 100,000,000 (e.g. 1 represents 0.00000001 OMNI, 100,000,000 represents 1.0 OMNI), which allows for the number of Omni Protocol coins or tokens to be specified with the same precision as bitcoins (eight decimal places)
-
for indivisible coins or tokens, the value in this field is the integer number of Omni Protocol coins or tokens (e.g. 1 represents 1 indivisible token)
-
-
Size: 64-bit signed integer, 8 bytes (same as Bitcoin Core)
-
Inter-dependencies: Property type
-
Valid values: 1 to 9,223,372,036,854,775,807 which represents
-
0.00000001 to 92,233,720,368.54775807 divisible coins or tokens
-
1 to 9,223,372,036,854,775,807 indivisible coins or tokens
-
-
Description: Specifies if the Omni Protocol coin or token to be created will be divisible or indivisible, and if that coin or token will replace or append an existing Smart Property
-
Size: 16-bit unsigned integer, 2 bytes
-
Inter-dependencies: Number of coins
-
Valid values:
-
1: New Indivisible tokens
-
2: New Divisible currency
-
65: Indivisible tokens when replacing a previous property
-
66: Divisible currency when replacing a previous property
-
129: Indivisible tokens when appending a previous property
-
130: Divisible currency when appending a previous property
-
-
Description: the seller’s response to a buyer’s offer to purchase
-
Size: 8-bit unsigned integer, 1 byte
-
Valid values:
-
1: Accept
-
2: Reject
-
3: Contact
-
-
Description: a variable length string terminated with a \0 byte
-
Size: variable, up to 255 bytes, plus the null terminator
-
Valid values: Unicode encoded with UTF-8
-
Description: number of blocks during which an action can be performed
-
Size: 8-bit unsigned integer, 1 byte
-
Valid values: 1 to 255
-
Description: Datetime, assuming UTC timezone (the same timezone used by the bitcoin blockchain)
-
Size: 64-bits standard unix timestamp, 8 bytes (note: seconds, not milliseconds)
-
Valid values: http://en.wikipedia.org/wiki/Unix_time, with precision to the second for computation and display, same as used by the Bitcoin protocol
-
Description: number of seconds during which an action can be performed
-
Size: 32-bit unsigned integer, 4 bytes
-
Valid values: 1 to 31,536,000 (365.0 days)
-
Description: the specific action to be applied to the sell offer by this transaction
-
Size: 8-bit unsigned integer, 1 byte
-
Valid values:
-
1: New
-
2: Update
-
3: Cancel
-
-
Description: the specific action to be applied to the sell offer by this transaction
-
Size: 8-bit unsigned integer, 1 byte
-
Valid values:
-
1: ADD
-
2: CANCEL-AT-PRICE
-
3: CANCEL-ALL-FOR-CURRENCY-PAIR
-
4: CANCEL-EVERYTHING
-
-
Description: the OMNI Protocol function to be performed
-
Size: 16-bit unsigned integer, 2 bytes
-
Inter-dependencies: Transaction version
-
Current Valid values:
-
Description: the version of the transaction definition, monotonically increasing independently for each transaction type
-
Size: 16-bit unsigned integer, 2 bytes
-
Required/optional: Required
-
Inter-dependencies: Transaction type
-
Valid values: 0 to 65535
Class A transactions were the first class of Omni Protocol transaction and store data in the blockchain by utilizing fake Bitcoin addresses to encode transaction data.
The transaction data is encoded into said fake Bitcoin address which is then used as an output in a single Bitcoin transaction satisfying the following requirements:
-
Has a single or the largest pay-to-pubkey-hash or pay-to-script-hash (since block height 322000) input with a valid signature to designate the sending address
-
Has an output for the recipient address (the ‘reference’ address)
-
Has an output for the exodus address
-
Has an output for the encoded fake address (the ‘data’ address)
-
Should have all output values above the ‘dust’ threshold (0.00005460 BTC as of Q2 2014) and preferable be equal.
-
Has exactly two non-Exodus outputs (one of which must be the data address) with a value equal to the Exodus output and/or has exactly one output with a sequence number +1 of the data address for reference output identification
-
Additional outputs are permitted for the remainder of the input (the ‘change’ address)
Further:
-
Exodus outputs are ignored in decoding
-
Any input not meeting the requirement for type (pay-to-pubkey-hash or pay-to-script-hash) will trigger the invalidation of the transaction
-
Only pay-to-pubkey-hash and pay-to-script-hash outputs will be considered for the reference address
-
Pay-to-script-hash output addresses will be the opaque script-hash address and not assume any decomposition into addresses which may be used in the redemption of such outputs
-
Pay-to-script-hash is enabled since block height 322000
Note
|
The sequence number for a given address is defined as a 1 -byte integer stored as the first byte of each ‘packet’. Sequence numbers are continuous with 0 following 255 (256=0, 255+1=0). |
Note
|
Should a transaction result in an edge case that provides conflicting reference address values for sequence numbers and equal outputs, the reference address identified via equal outputs will take precedence. |
As there is no private key associated with these fake addresses they are inherently unspendable. This creates concerns around blockchain bloat, especially within the UTXO (Unspent Transaction Output) set as each use of a fake address adds an unspent output to the UTXO dataset that will never be redeemed, thus growing (or ‘bloating’) it.
As the UTXO set is designed to be memory resident it is thus in the interests of Bitcoin to avoid UTXO bloat to minimize the memory requirement for client implementations.
Class B transactions were developed to address this issue by using provably redeemable outputs. Class A (and B) transactions are thus considered deprecated and are supported for backwards compatibility only.
Note
|
Class A transactions are restricted to the ‘simple send’
transaction type only. All other Omni transaction types are supported by
Class B and Class C transactions only. Client implementations should utilize
Class C transactions for all transaction types that will fit in an OP_RETURN output,
falling back to Class B for larger (and less common) transactions.
|
Class B transactions attempt to address the UTXO ‘bloat’ issue by storing data in the blockchain by utilizing ‘1-of-n’ multisignature outputs where one of the signatories is the sender or another public key address the sender has designated.
By adopting a ‘1-of-n’ approach (credit Tachikoma @ bitcointalk) we can increase n to the number of packets (public keys) needed to store the transaction data while maintaining the ability of the sender or their designated party to redeem the output.
Note
|
The reference client currently supports a maximum value of 3 for n. As one signatory should be the sender for redemption purposes, there is a current limit of 2 data packets per output. A number of multisig outputs can be combined to increase the space available for transaction data as required. On decoding all Omni Protocol packets from all multisig outputs are ordered via their sequence number and evaluated as a continuous data stream. |
Transaction data is encoded into one or a number of compressed public keys which are obfuscated and then should have their last byte manipulated to form a valid ECDSA point. These compressed public keys then can be included as signatories in a multisig output ordered by their sequence number.
The size of an Omni Protocol packet in a compressed public key is thus 31 bytes (33 bytes minus the first and last bytes for the key identifier (02) and ECDSA manipulation byte). The Omni Protocol packet reserves the first byte for the sequence number, providing a total of 30 bytes per packet for Omni Protocol transaction data. The range of sequence numbers in a Class B transaction is 1 to 255, providing for a total 7,650 bytes maximum actual transaction data storage per Omni Class B transaction.
Sequence numbers are again used to order the packets (again first byte of the packet), however as we no longer need to use sequence numbers to identify the recipient (reference) address we are able to start the sequence at one (we do not start the sequence at zero due to our need for a positive sequence number in obfuscation).
Obfuscation is performed by SHA256 hashing the sender’s address S times (where S is the sequence number) and taking the first 31 bytes of the resulting hash and XORing with the 31 byte Omni packet. Multiple SHA256 passes are performed against an uppercase hex representation of the previous hash.
EXAMPLE: The following provides example output for an obfuscated Omni packet (where and XX is the last byte reserved for ECDSA point validity manipulation):
Reference address |
{1CdighsfdfRcj4ytQSskZgQXbUEamuMUNF} |
SHA256 hash (S times) of address |
{1D9A3DE5C2E22BF89A1E41E6FEDAB54582F8A0C3AE14394A59366293DD130C}59 |
Cleartext packet |
02{0100000000000000010000000002faf0800000000000000000000000000000}XX |
Obfuscated packet |
02{1C9A3DE5C2E22BF89B1E41E6FED84FB502F8A0C3AE14394A59366293DD130C}XX |
Once the obfuscated Omni packet is prepared, the key identifier (02) is prefixed and a random byte compressed public key is then run across a check to ensure the key is a valid ECDSA point. If the key fails this check, the last byte is simply rotated with a different random byte and tested again until the key forms a valid ECDSA point.
These compressed public key ‘packets’ can then be included in one or multiple OP_CHECKMULTISIG output along with the senders public key. A single transaction must be constructed satisfying the following requirements: * Has a single or the largest pay-to-pubkey-hash or pay-to-script-hash (since block height 322000) input with a valid signature to designate the sending address * Has an output for the recipient address (the ‘reference’ address) * Has an output for the exodus address * Has one or more n-of-m OP_CHECKMULTISIG outputs each containing at least two public keys whereby the first should be a valid public key address designated by the sender which may be used to reclaim the bitcoin assigned to the output, the second must be Omni ‘data package n’ and the third may be ‘data package n+1’ * Omni ‘data packages’ appear in order by their sequence number * Additional outputs are permitted
Further:
-
Exodus outputs are ignored in decoding
-
Any input not meeting the requirement for type (pay-to-pubkey-hash or pay-to-script-hash) will trigger the invalidation of the transaction
-
Only pay-to-pubkey-hash or pay-to-script-hash outputs will be considered for the reference address
-
Pay-to-script-hash output addresses will be the opaque script-hash address and not assume any decomposition into addresses which may be used in the redemption of such outputs
-
Pay-to-script-hash is enabled since block height 322000
-
Only multisig outputs will be considered for the data packets
-
If there are multiple outputs remaining, the first output to the sending address (if such an output exists) will be ignored as change
-
The reference address will be determined by the remaining output with the highest vout index
Note
|
Class B transactions are deprecated, except for transactions where the payload is too large to fit in an OP_RETURN. Client implementations should generate Class C transactions when they can fit in a single OP_RETURN output, Class B transactions for larger (but typically infrequent) transactions, and need to be able to read Class A or Class B transactions. |
-
payloads are embedded in OP_RETURN outputs with "omni" as four ASCII bytes (hex: 6f6d6e69) being the marker prefix
-
Output to Exodus address no longer required
The Bitcoin script opcode OP_RETURN marks a transaction output as unspendable (to avoid UTXO-set bloat) and allows embedding data in that transaction output.
The current maximum payload size in accordance with Bitcoin consensus and relay rules is 76 bytes (80 bytes minus 4 bytes for the "omni" marker prefix.)
In these examples +
is used as a concatenation operator.
The Omni Core implementation technically allows more complicated transactions, with multiple OP_RETURN outputs and/or multiple data pushes for each OP_RETURN, but these transactions are non-standard, not relayed by Bitcoin Core, and not recommended.
-
multiple push operations are allowed and simply ignored.
-
there can be more than one OP_RETURN output and payload per transaction. If there are multiple, they are combined.
166a146f6d6e69000000000000001f0000000df8475800
Decoded:
16 <- push 22 byte
6a <- opcode OP_RETURN
14 <- push 20 byte
6f6d6e69000000000000001f0000000df8475800 <- 20 byte payload with marker 6f6d6e69
But also allowed:
OP_RETURN (push) [6f6d6e69] (push) [aaaa] (push) [bbbbcc]
OP_RETURN (push) [6f6d6e69][dddd]
OP_RETURN (push) [ffffffffff0101]
OP_RETURN (push) [6f6d6e69] (push) [eeee] (push) [ffgg]
Resulting in a payload with:
aaaabbbbccddddeeeeffgg
The outputs with prefix are considered, the prefix removed, all pushes combined and then all payloads combined.
These are the C++ unit tests from Omni Core. We’re not sure if they should be left in the specification, but here they are for now:
Each transaction definition has its own version number to enable support for changes to each transaction definition. Up thru version 0.3.5 of this spec, the Transaction type field was a 4 byte integer. Since there were only 17 transactions identified, the upper 3 bytes of the field had a value of 0. For all spec versions starting with 0.4, the first field in each transaction message is the 2 byte version number, with an initial value of 0 and the Transaction type field is a 2 byte integer. So, each client must examine the first two bytes of the transaction message to determine how to parse the remainder of the message. If the value is 0, then the message is in the format specified in version 0.3.5 of this spec. If the value is at least 1, then the message is in the format associated with that version number.
Omni Protocol transactions are not reversible except as explicitly indicated by this spec.
Any Omni transaction from any address that attempts to transfer, reserve, commit coins, or put coins in escrow while that address’s available balance for that currency identifier is 0 will be invalidated.
Transfers are unconditional payments from one Omni address to another address, set of addresses, or proportionally to owners of a specific property.
Description: Transaction type 0 transfers coins in the specified currency from the sending address to the reference address, defined in Omni Payload Format. This transaction can not be used to transfer bitcoins.
In addition to the validity constraints on the message field datatypes, the transaction is invalid if any of the following conditions is true:
-
the sending address has zero coins in its available balance for the specified currency identifier
-
the amount to transfer exceeds the number owned and available by the sending address
-
the specified currency identifier is non-existent
-
the specified currency identifier is 0 (bitcoin)
A Simple Send to a non-existent address will destroy the coins in question, just like it would with bitcoin.
[Future: Note that if the transfer comes from an address which has been marked as “Savings”, there is a time window in which the transfer can be undone.]
Say you want to transfer 1 OMNI to another address. Only 16 bytes are needed. The data stored is:
Field | Type | Example |
---|---|---|
Transaction version |
0 |
|
Transaction type |
0 |
|
Currency identifier |
1 (OMNI) |
|
Amount to transfer |
100,000,000 (1.0 coins) |
Description: Transaction type 3 transfers coins in the specified currency from the sending address to the current owners of that currency. The current owners are all the addresses, excluding the sender’s address, that have a non-zero balance of the specified currency when the transaction message is processed. The Amount to transfer must be divided proportionally among the current owners based upon each owner’s current available balance plus reserved amount, excluding the amount owned by the sender. If there are no owners of the property excluding the sending address, the transaction is invalid.
The sending address must be charged a transfer fee for each address that receives coins as a result of this transaction. The fee is: * 0.00000001 OMNI for currencies in the OMNI ecosystem, and * 0.00000001 Test OMNI for currencies in the Test OMNI ecosystem.
See Currency Identifier, above.
Be aware that some owners of the specified currency might receive zero coins due to rounding in calculating the number of coins for each owner. See the Implementation Note below.
This transaction can not be used to transfer bitcoins.
In addition to the validity constraints on the message field datatypes, the transaction is invalid if any of the following conditions is true: * the sending address has zero coins in its available balance for the specified currency identifier * the amount to transfer exceeds the number owned and available by the sending address * the specified currency identifier is non-existent * the specified currency identifier is 0 (bitcoin) * the sending address does not have a sufficient available balance to pay the transfer fee * the sending address owns all the coins of the specified currency identifier
Implementation Note: It is possible, even likely, that the number of coins calculated to be transferred to an owner’s address will have to be rounded to comply with the precision for representing quantities of that coin. To reward the owners of the largest quantities and to try to ensure they receive full distributions, the following method must be used: compute the amount for the largest holder and, if necessary, round that amount up to the nearest unit that can be represented for the currency. Then subtract that rounded amount from the total to be distributed and repeat for the next largest holder until there are no more coins to be distributed. This means that holders of lesser amounts might receive zero coins from the distribution. When there are multiple owners with exactly the same number of coins, compute the distributions to those in alphabetical order by address.
Say you have grown wealthy and wish to gift all 1000 of your own Quantum Miner digital tokens to the other people holding those tokens. The message to do so will use 16 bytes:
-
Transaction type = 3
-
Currency identifier = 6 for Quantum Miner Tokens
-
Amount to transfer = 100,000,000,000 (1000.00000000 Quantum Miner Tokens)
The protocol will split up the 1000 Quantum Miner tokens and send them to the other holders of those tokens, according to how many tokens they have. When using currencies other than OMNI, a small fee will be deducted (see fees above). The sender is also charged a transfer fee based on the number of addresses that receive any of the 1000 Quantum Miner tokens (as described earlier).
Note to users: please make sure your proposed use case is legal in your jurisdiction!!
The Omni Protocol allows users to trade coins without trusting a centralized website. When trading OMNI for bitcoins, this can be rather cumbersome, since it isn’t possible to automatically match bids with asks, since we can’t force the bidder to send bitcoins when a matching ask is found. When trading OMNI for other Omni Protocol currencies, bids and asks are matched automatically.
Consequently, the messages below are different for OMNI/bitcoin exchange than they are for exchange between OMNI and other Omni Protocol currencies, and the resulting UI must also be different, reflecting both the one-sided nature of bitcoin/OMNI exchange as well as the additional anti-spam fees and race conditions inherent in the system.
Description: Transaction type 20 posts the terms of an offer to sell OMNI or Test OMNI for bitcoins. A new sell offer is created with Action = 1 (New). Valid currency identifier values for this transaction are 1 for MSC or 2 for Test MSC.
If the amount offered for sale exceeds the sending address’s available balance (the amount not reserved, committed or in escrow), this indicates the user is offering to sell all coins that are available at the time this sell offer is published. The amount offered for sale, up to the amount available, must be reserved from the available balance for this address much like any other exchange platform. (For instance: If an address owns 100 MSC and it creates a “Sell Order” for 100 MSC, then the address’s available balance is now 0 MSC, reserving 100 MSC.) After the sell offer is published, any coins received by the address are added to its then current available balance, and are not included in the amount for sale by this sell offer. The seller could update the sell offer to include these newly acquired coins, see Change a Coin Sell Offer below.
The unit price of the sell offer is computed from two of the fields in the transaction message: the “Amount for sale” divided by the “Amount of bitcoins desired”. Once the unit price is computed, the “Amount of bitcoins desired” value can be discarded.
Note: An address cannot create a new Sell OMNI for Bitcoins offer while that address has any active offer that accepts Bitcoins. Currently, this includes an active Sell OMNI for Bitcoins offer (one that has not been canceled or fully accepted and full payment received) and an active New Property Creation via Crowdsale with Variable number of Tokens that accepts Bitcoins.
Say you want to publish an offer to sell 1.5 OMNI for 1000 bitcoins. Doing this takes 34 bytes:
Field | Type | Example |
---|---|---|
Transaction version |
1 |
|
Transaction type |
20 |
|
Currency identifier |
1 (OMNI) |
|
Amount for sale |
150,000,000 (1.5 coins) |
|
Amount of bitcoins desired |
100,000,000,000 (1000.0 coins) |
|
Payment window |
10 (10 blocks to send payment after counter-party accepts these terms) |
|
Minimum bitcoin transaction fee |
10,000,000 (buyer must pay 0.1 BTC fee to the miner, discouraging fake offers) |
|
Action |
1 (New offer) |
Note that some trading of Test MSC was done with version 0 of this message which did not have the Action field. Those transactions are treated as Action=3 (Cancel offer) when the Amount for sale is zero. For version 0 of this message and Amount for sale = 0 (Cancel offer), the values in the following fields are not tested for validity: * Amount of bitcoins desired * Time limit in blocks * Minimum bitcoin transaction fee
For version 0 of this message and Amount for sale is non-zero, it is treated as Action=1 (New offer) unless there is already an offer outstanding from this address for the same Currency identifier, in which case it is treated as Action = 2 (Update offer).
An offer to sell coins can be changed by using Action = 2 (Update) until either: there are valid corresponding purchase offers (transaction type 22) for the whole amount offered, or the sell offer is canceled. The Currency identifier cannot be changed.
The change will apply to the balance that has not yet been accepted with a purchase offer. The stored unit price must be updated using the updated Amount for sale and Amount of bitcoins desired. The Amount desired value can be discarded after the unit price is updated. The UI must indicate if the update was successful and how many coins were purchased before the update took effect.
The amount reserved from the available balance for this address will be adjusted to reflect the new amount for sale. Note that the amount reserved as a result of the update is based on the available balance at the time of the update plus the existing sell offer amount not yet accepted at the time of the update.
Say you decide you want to change an offer, e.g. the number of coins you are offering for sale, or change the asking price. Send the transaction with the new values and the values that are not changing and Action = 2 (Update) before the whole amount offered has been accepted. Note that while the portion of an offer which has been accepted cannot be changed, sending an update message still has an effect, in that it affects any coins which have not been accepted, and it affects accepted coins if the buyer fails to send payment.
A currency sell offer can be canceled by using Action = 3 (Cancel) until the offer has been fully accepted by valid purchase offers (Purchase OMNI with Bitcoins). When a sell offer is canceled, the associated coins are no longer reserved.
When canceling a sell offer, the values in the following fields are not tested for validity: * Amount for sale * Amount of bitcoins desired * Time limit in blocks * Minimum bitcoin transaction fee
The cancel will apply to the amount that has not yet been accepted. The UI must indicate if the cancellation was successful and how many coins were not sold.
If you want to cancel an offer, use Action = 3 (Cancel) and send the transaction before the full amount for sale has been accepted. Note that while the portion of an offer which has been accepted cannot be canceled, sending the cancel message still has an effect, in that it cancels any portion of the offer which has not been accepted, and it prevents accepted coins from being relisted if the buyer fails to send payment.
Description: Transaction type 22 posts acceptance of an offer to sell OMNI for bitcoins. All or some of the coins offered can be purchased with this transaction.
The reference address must point to the seller’s address, to identify whose offer you are accepting. The purchaser’s address must be different than the seller’s address.
If you send an offer for more coins than are available at the time your transaction gets added to a block, your amount bought will be automatically adjusted to the amount still available. When a Purchase Offer is sent to an address that does not have a matching active Sell Offer, e.g. the Sell offer has been canceled or is all sold out, the Purchase Offer must be invalidated. It is not valid to send a Purchase Offer to an address if the sending address has an active Purchase Offer (not fully paid for and time limit not yet reached) with that address.
Note: Your total expenditure on bitcoin transaction fees while accepting the purchase must meet the minimum fee specified in the Sell Offer in order for the transaction to be valid.
You must send the appropriate amount of bitcoins before the time limit expires to complete the purchase. Note that you must send the bitcoins from the same address which initiated the purchase. If you send less than the correct amount of bitcoins, your purchase will be adjusted downwards once the time limit expires. The remaining coins will be added back to those available in the Sell Offer if it’s still active. If you send more than the correct amount of bitcoins, your bitcoins will be lost (unless the seller chooses to return them to you). If you do not send complete payment before the time limit expires, the unpurchased coins will be added back to those available in the Sell Offer if it’s still active.
Please note that the buyer is allowed to send multiple bitcoin payments between the Purchase Offer and expiration block which are accumulated and used to adjust the Purchase Offer accordingly. The buyer’s OMNI available balance is credited with the purchased coins when each bitcoin payment is processed.
In order to make parsing Omni Protocol transactions easier, you must also include an output to the Exodus Address when sending the bitcoins to complete a purchase of OMNI. The output can be for any amount, but should be at least as high as the amount which is considered as dust threshold by a majority of Bitcoin nodes so that propagation of the transaction within the network and confirmation by a miner is not delayed.
Other Omni Protocol messages (for instance if the buyer wants to change his offer) are not counted towards the actual purchase, even though bitcoins are sent to the selling address as part of encoding the messages.
Say you see an offer such as the one listed above, and wish to initiate a purchase of those coins. Doing so takes 16 bytes:
Field | Type | Example |
---|---|---|
Transaction version |
0 |
|
Transaction type |
22 |
|
Currency identifier |
1 (OMNI) |
|
Amount to be purchased |
130,000,000 (1.3 coins) |
Description: Transaction type 21 is used to both publish and accept an offer to sell coins in one Omni Protocol Currency for coins in another Omni Protocol Currency.
If the amount offered for sale exceeds the sending address’s available balance (the amount not reserved, committed or in escrow), the transaction is invalid. The amount offered for sale, up to the amount available, must be reserved from the available balance for this address much like any other exchange platform. (For instance: If an address owns 100 MSC and it creates a “Sell Order” for at least 100 MSC, then the address’s available balance is now 0 MSC, reserving 100 MSC.) After the sell order is published, any coins received by the address are added to its then current available balance, and are not included in the amount for sale by this sell order. The seller could update the sell order to include these newly acquired coins, see Change a Transaction Type 21 Coin Sell Order below.
The new sell order’s unit price is computed from two of the fields in the transaction message: the “Amount desired” divided by the “Amount for sale”. An existing order’s original unit price is used to match against new orders. The unit price does not change. The currency id for sale must be different from the currency id desired. Both currency id’s must refer to existing currencies.
To accept an existing sell order, an address simply publishes the same message type with an inverse offer (e.g. selling Goldcoins for OMNI in the example below) at a unit price which is greater than or equal to the existing sell order’s unit price. The protocol then finds existing sell orders that qualify (match), possibly including existing sell orders from that same address.
A liquidity bonus for the owners of existing sell orders provides an incentive for people to put their coins up for sale at a price which does not get filled instantly, increasing available liquidity on the exchange. The liquidity bonus for the owner of a matching sell order is taken from the amount paid by the new sell order. The liquidity bonus is 0.3% of the amount paid by the new sell order, rounded to the nearest .00000001 for divisible tokens or to the nearest whole number for indivisible tokens. The liquidity bonus percentage and/or calculation may change in the future.
The following table shows examples of the liquidity bonus based on the new order’s amount for sale and the existing order’s minimum amount desired, for divisible coins. This table does not show the new order’s minimum amount desired or the existing order’s amount for sale, which are not subject to the liquidity bonus.
New Order Amt for Sale | Existing Order Min Amt Desired | Amt Transferred | Liquidity Bonus Paid | New Order Remainder for Sale | Existing Order Remainder Desired |
---|---|---|---|---|---|
100.3 |
100.0 |
100.0 |
0.3 |
0.0 |
0.0 |
100.0 |
100.0 |
99.70089731 |
0.29910269 |
0.0 |
0.29910269 |
125.0 |
100.0 |
100.0 |
0.30 |
24.7 |
0.0 |
50.0 |
100.0 |
49.85044865 |
0.14955135 |
0.0 |
50.14955135 |
The following table shows examples of the liquidity bonus based on the new order’s amount for sale and the existing order’s minimum amount desired, for indivisible coins. This table does not show the new order’s minimum amount desired or the existing order’s amount for sale, which are not subject to the liquidity bonus.
New Order Amt for Sale | Existing Order Min Amt Desired | Amt Transferred | Liquidity Bonus Paid | New Order Remainder for Sale | Existing Order Remainder Desired |
---|---|---|---|---|---|
1003 |
1000 |
1000 |
3 |
0 |
0 |
1000 |
1000 |
997 |
3 |
0 |
3 |
502 |
502 |
500 |
2 |
0 |
2 |
500 |
1000 |
499 |
1 |
0 |
501 |
500 |
500 |
499 |
1 |
0 |
1 |
100 |
100 |
100 |
0 |
0 |
0 |
125 |
100 |
100 |
0 |
25 |
0 |
The coins from each matching order and the new order are exchanged between the corresponding addresses at the unit price specified by the matching order plus the liquidity bonus amount until the full amount for sale in the new order is transferred to the address of the matching sell order or there are no more matching orders. In other words, every order is a “sell” order (complete when all tokens are sold), and there are no “buy” orders (complete when all tokens are purchased). If a new order gets a more favourable price than they requested, they will receive more coins, not spend fewer coins.
Notes on rounding, with me (the new order) purchasing from Bob (the existing order):
-
First determine how many representable (indivisible) tokens I can purchase from Bob (using Bob’s unit price)
-
This implies rounding down, since rounding up is impossible (would require more money than I have)
-
Example: if Bob has 9 indivisible tokens for sale, and I can afford 8.9 of them, round down to 8
-
-
If the amount I would have to pay to buy Bob’s tokens at his price is fractional, always round UP the amount I have to pay
-
This will always be better for Bob. Rounding in the other direction will always be impossible (would violate Bob’s required price)
-
If the resulting adjusted unit price is higher than my price, the orders did not really match (no representable fill can be made)
-
Example: if those 8 tokens would cost me 15.1 indivisible tokens, I must pay 16 tokens, or NO SALE
-
Note: After a partial fill, the unit price for an order does not change, (this is to avoid orders moving around in the order book). For example, if the initial price was 23 for 100, the price will remain at that ratio regardless of any partial fills.
It is valid for the purchaser’s address to be the same as the seller’s address.
An existing order matches the new order when all of the following conditions are met:
-
the existing order’s Currency id for sale is the same as the new order’s Currency id desired
-
the existing order’s Currency id desired is the same as the new order’s Currency id for sale
-
the existing order’s unit price is less than or equal to the reciprocal of the new order’s unit price
-
the existing order is still open (not completely sold or canceled)
Existing orders that match are sorted as follows to be applied to the new order:
-
by unit price, ascending (best price for the new order first)
-
then by transaction block number, ascending chronological order (oldest first)
-
then by transaction position within the block, ascending order (oldest first)
If there are no matches for the new sell order or the aggregate amount desired in the matching orders is less than the amount for sale in the new sell order, the new sell order must be added to the list of existing sell orders, with the remaining amount for sale at the original unit price. This order is now a candidate for matching against future sell orders. Note that when only some coins from an existing order are purchased, the remaining coins from that order are still for sale at the original unit price.
Say you want to publish an offer to sell 2.5 OMNI for 50 GoldCoins (hypothetical Omni Protocol coins which each represent one ounce of gold and described later in this document). For the sake of example, we’ll assume that GoldCoins have currency identifier 3. Doing this takes 29 bytes:
Field | Type | Example |
---|---|---|
Transaction version |
0 |
|
Transaction type |
21 |
|
Currency identifier for sale |
1 for OMNI |
|
Amount for sale |
250,000,000 (2.5 coins) |
|
Currency identifier desired |
3 for GoldCoin |
|
Amount desired |
5,000,000,000 (50.0 coins) |
|
Action |
1 (ADD new funds for sale) |
Although the formatting of this message technically allows trading between any two currencies/properties, we currently require that either the currency id for sale or the currency id desired be OMNI (or Test OMNI), since those currencies are the universal token of the protocol and the only ones which can be traded for bitcoins on the distributed exchange (and thus exit the Omni ecosystem without trusting a centralized exchange). This provides each currency and property better liquidity than a multi-dimensional order book ever could, and it reduces the complexity of the software. If another currency becomes widely used in the Omni Protocol, we may allow other currencies (such as a USDCoin) to be used in a similar way, with a tiny amount of MSC being automatically purchased and burned with each trade (see the section on fees above) when a trade is completed and neither currency being traded is OMNI.
An offer to sell coins can be changed or cancelled by publishing additional transactions with Metadex Sell offer sub-action variations:
-
Action = 1 (ADD) orders are merged (both in the database and the UI) when their unit prices are exactly the same.
-
Action = 2 (CANCEL-AT-PRICE) cancells open orders for a given set of currencies at a given price. It is required that the currency identifiers and price exactly match the order to be canceled.
-
Action = 3 (CANCEL-ALL-FOR-CURRENCY-PAIR) cancels all open orders for a given set of two currencies (one side of the order book).
-
Action = 4 (CANCEL-EVERYTHING) can be used to cancel all open orders for all currencies within one ecosystem, if Currency identifier for sale and Currency identifier desired are within the same ecosystem, otherwise all open orders for all currencies of both ecosystems are cancelled.
When using Action = 3 (CANCEL-ALL-FOR-CURRENCY-PAIR) the validity of the following fields is not tested: * Amount for sale * Amount desired
When using Action = 4 (CANCEL-EVERYTHING) the validity of the following fields is not tested: * Currency identifier for sale * Amount for sale * Currency identifier desired * Amount desired
Any time coins are added, whether merged with another order or not, the same matching process is run as for a new order as described above.
With any changes, the amount reserved from the available balance for this address must be adjusted to reflect the new amount for sale. Note that the amount for sale as a result of the update is limited by the available balance at the time of the update plus the existing sell order amount not yet matched at the time of the update.
The UI must indicate if the update was successful and how many coins were purchased before the update took effect.
The Omni Protocol supports the creation of property tokens to be used for titles, deeds, user-backed currencies, and even investments in a company. Property tokens can be bought, sold, transferred, and used for betting, just as Omni Protocol currencies are.
Properties are awarded currency identifiers in the order in which they are created. OMNI is currency identifier 1 (bitcoin is 0), and Test OMNI have currency identifier 2. Additional properties and currencies therefore start at ID #3. Properties issued and traded using real MSC are kept completely distinct from those issued and traded using Test MSC, so the ID numbering systems for the two ecosystems are independent. Test OMNI properties have the most significant bit set to distinguish them from real properties, and they cannot be traded against real OMNI nor otherwise interact with non-test properties. Test MSC property IDs also start numbering from 3, but with the most significant bit set. In sandbox environments using only Test MSC, these IDs can be displayed without the MSB set, for easier reading.
Every property has a Property type, which defines whether it is divisible or not and whether the property replaces or appends a previous property. To create 1,000,000 units of a divisible currency, choose property type 2 and specify 100,000,000,000,000 for the number of properties (1 million divisible to 8 decimal places). For 1,000,000 indivisible tokens for a company, choose property type 1 and specify 1,000,000 for the number of properties. The difference between divisible and indivisible property types is how they are displayed (i.e. where the decimal point goes) and the range of valid values that can be specified in a transaction message field (see Number of coins).
The attributes of an existing property cannot be changed. However, a new property can be created to replace or append an existing property. Only the address that issued a property can replace or append that property. Attempts by other addresses are invalid. A replaced property can still be used and traded as normal, but the UI should indicate to the user that a newer version of the property exists and link to it. To indicate that the issuer is abandoning a property entirely: * set Previous Property ID to that property’s id, * set Number Properties to zero, and * use one of the “replace” values for Property Type (see Transaction types 50 and 51, below).
A property can be replaced and appended multiple times, even abandoning and un-abandoning it more than once. Appended properties must not be treated as the same asset in the UI or protocol parsers (the appended properties have independent values). When displaying a property, the UI should provide links to any related properties. Related properties are the property which was replaced or appended by this property (if there is one) as well as any properties from the same issuer which replace or append this property.
The Ecosystem for the property must be the same as the ecosystem for the “Currency identifier desired”, i.e. both must be in the OMNI ecosystem or both must be in the Test OMNI ecosystem.
Currently only new property creation is supported, and the append/replace property types (65/66/129/130) will be made live at block #TBD.
Any time the name of a property is displayed, the ID number of the property must also be displayed with it in the format “NAME (ID)”, to avoid name collisions. For instance, “Quantum Miner (8)”. This is very important to prevent a malicious user from creating a property to impersonate another property.
To help distinguish legitimate companies and ventures from scams, spam, and experiments, the Omni Protocol allows users to spend OMNI for the purpose of promoting a smart property. When UI clients display smart properties, the default ordering should be based on how many OMNI have been spent for promoting the property, adjusted for how long ago the OMNI were spent. Details on promoting a smart property by spending OMNI and how that affects sort ordering can be found below.
The “Property Data” field is general-purpose text, but can be used for things like storing the hash of a contract to ensure it is in the block-chain at property creation (i.e. “Proof of Existence”).
All property creation transaction types (i.e. 50, 51, 54) can be restricted such that only a specified list of addresses can use the resulting property tokens. This can be useful when the issuer wants to restrict their token to a set of approved people, such as those who have provided identifying documentation in compliance with KYC (know your customer) AML (anti-money-laundering) laws. When creating a property which should be restricted to a set of addresses, simply set the reference address to be the address which created the list of approved addresses. Addresses which are not on the list will not be able to receive or otherwise interact with the token (transactions attempting to do so are invalid). However, addresses which are removed from the list can still send their restricted tokens to another approved address using simple send, but they cannot receive new coins or use the coins in any other way. This prevents tokens from effectively being destroyed when addresses are removed from the approved list. To create a list of addresses, the "Create a List of Addresses" transaction was proposed and withdrawn (see OLE-099).
Description: Transaction type 50 is used to create a new Smart Property with a fixed number of tokens.
If creating a title to a house or deed to land, the number of properties should be 1. Don’t set number of properties to 10 for 10 pieces of land – create a new property for each piece of land, since each piece of land inherently has a different value, and they are not interchangeable.
Once this property has been created, the tokens are owned by the address which broadcast the message creating the property.
In addition to the validity constraints for each message field type, the following conditions must be met in order for the transaction to be valid: * “Previous Property ID” must be 0 when “Property Type” indicates a new property * When “Property Type” indicates a property is being replaced or appended, “Previous Property ID” must be a currency ID created by the address * “Property Name” must not be blank or null
Say you want to create 1,000,000 digital tokens for your company “Quantum Miner”. Doing so will use a varying number of bytes, due to the use of null-terminated strings. This example uses 80 bytes:
Field | Type | Example |
---|---|---|
Transaction version |
0 |
|
Transaction type |
50 |
|
Ecosystem |
1 (OMNI ecosystem) |
|
Property Type |
1 (new Indivisible tokens) |
|
Previous Property ID |
0 (for a new smart property) |
|
Property Category |
“Companies\0” (10 bytes) |
|
Property Subcategory |
“Bitcoin Mining\0” (15 bytes) |
|
Property Name |
“Quantum Miner\0” (14 bytes) |
|
Property URL |
“tinyurl.com/kwejgoig\0” (21 bytes) |
|
Property Data |
“\0” (1 byte) |
|
Number Properties |
1,000,000 (indivisible tokens) |
Description: Transaction type 51 is used to initiate a crowdsale which creates a new Smart Property with a variable number of tokens, determined by the number of tokens purchased and issued during the the crowdsale.
Effective with version 1 of Transaction type 51 and block #(TBD), a single crowdsale is able to accept multiple currencies, including bitcoins (currency id 0), for purchases of a Smart Property in a single crowdsale. See Accepting Multiple Currencies in a Crowdsale below.
The crowdsale is active until any of the following conditions occurs, which causes the crowdsale to be closed permanently: * there is a block with a blocktime greater than or equal to the crowdsale’s “Deadline” value * the crowdsale is manually closed * the maximum number of tokens that can be issued by a crowdsale has been credited (92,233,720,368.54775807 divisible tokens or 9,223,372,036,854,775,807 indivisible tokens, see field Number of Coins).
An address may have only one crowdsale active at any given time, eliminating the need for participants to specify which crowdsale from that address they are participating in when they purchase. See Participating in a crowdsale below.
Tokens credited to each crowdsale participant and the crowdsale owner are immediately added to the available balance belonging to the respective address and can be spent or otherwise used by that address. Funds raised are added to the available balance belonging to the crowdsale owner’s address as soon as they are received and can be spent or otherwise used by that address.
Note: It is strongly recommended that the UI provide a clear indication when the funds received by a crowdsale are being transferred to another address or reserved while the crowdsale is still active.
To provide an incentive for prospective crowdsale participants to purchase sooner rather than later, the issuer can specify an initial early bird bonus percentage for crowdsale purchasers of new smart properties. The early bird bonus percentage decreases linearly each second from the crowdsale start blocktime to zero at the crowdsale deadline.
The early bird bonus percentage for crowdsale purchasers of new smart properties is calculated the same way as was used in the original distribution of OMNI by the Exodus Address (see Initial Token Distribution via the “Exodus Address”):
EBpercentage = ( (“Deadline” value in seconds - transaction timestamp in seconds) / 604800) * “Early bird bonus %/week” value
The number of tokens credited to the purchaser is:
(1 + (EBpercentage / 100.0) ) * “Number Properties per Unit Invested” value * the number of coins sent by the purchaser
Note: To make it easier for issuers, a client UI could let the user enter an initial early bird bonus percentage and then convert that to the weekly percentage value required by the Transaction type 51 message. For example, an initial early bird bonus percentage of 30% would convert to “Early bird bonus %/week” value = 7 for a 30 day crowdsale. This would be particularly helpful for crowdsale lengths that are not a multiple of 7 days. Similarly, a client UI could do a complementary conversion in order to present the current early bird bonus percentage to prospective crowdsale participants.
The issuer may choose to receive a number of tokens in proportion to the number of tokens credited for each purchase. The “Percentage for issuer” value is used to calculate the number of additional tokens generated and credited to the issuer’s address as follows:
number of tokens credited to the purchaser * (“Percentage for issuer” value / 100.0)
The client must ensure that the number of tokens credited to the purchaser plus the number of tokens credited to the issuer will not cause the total number of tokens issued in the crowdsale to exceed the maximum number of tokens that can be issued. If that condition occurs, the client must reduce the number of tokens for the purchaser and the issuer so they both receive the correct percentages and the number of tokens issued as a result of this purchase equals the number of tokens remaining that can be issued. This is a partial purchase. It is left to the issuer to respond to any requests for refunds due to partial purchases.
The following expression may be used to calculate the maximum number of tokens that are available for purchase such that the current early bird bonus percentage and the Percentage for issuer can be applied without exceeding the maximum number of tokens that can be issued:
(MaxNum - Issued) / ( (1 + (EBpercentage / 100.0) ) * (1 + (“Percentage for issuer” value / 100.0) ) )
where: * MaxNum is the maximum number of tokens that can be issued * Issued is the number of tokens issued prior to this purchase
In addition to the validity constraints for each message field type, the following conditions must be met in order for the transaction to be valid: * “Previous Property ID” must be 0 when “Property Type” indicates a new property * When “Property Type” indicates a property is being replaced or appended, “Previous Property ID” must be a currency ID created by the address * “Property Name” must not be blank or null * “Currency Identifier Desired” must be 0, 1, or 2 or an existing Smart Property currency ID * “Deadline” must be greater than the crowdsale start blocktime
Say that instead of creating tokens and selling them, you’d rather do a kickstarter-style crowdsale to raise money for your “Quantum Miner” venture, with investors getting tokens for Quantum Miner in proportion to their investment, and the total number of tokens distributed being dependent on the amount of investment received. You want each OMNI invested over the next four weeks (ending, for example, at midnight UTC January 1st, 2215) to be worth 100 tokens of Quantum Miner, plus an early-bird bonus of 10%/week for people who invest before the deadline, including partial weeks. You also wish to grant yourself a number of tokens equal to 12% of the tokens distributed to investors as compensation for all your R&D work so far. This grant to yourself creates tokens in addition to the tokens distributed to investors. This transaction message will use a varying number of bytes, due to the use of null-terminated strings. This example uses 101 bytes:
Field | Type | Example |
---|---|---|
Transaction version |
0 |
|
Transaction type |
51 |
|
Ecosystem |
1 (OMNI ecosystem) |
|
Property Type |
1 (new Indivisible tokens) |
|
Previous Property ID |
0 (for a new smart property) |
|
Property Category |
“Companies\0” (10 bytes) |
|
Property Subcategory |
“Bitcoin Mining\0” (15 bytes) |
|
Property Name |
“Quantum Miner\0” (14 bytes) |
|
Property URL |
“tinyurl.com/kwejgoig\0” (21 bytes) |
|
Property Data |
“\0” (1 byte) |
|
Currency Identifier Desired |
1 for OMNI |
|
Number Properties per Unit Invested |
100 indivisible tokens |
|
Deadline |
January 1st, 2215 00:00:00 UTC (must be in the future) |
|
Early Bird Bonus %/Week |
10 |
|
Percentage for issuer |
12 |
A single crowdsale can accept multiple currencies for participation in the crowdsale. This is accomplished, while the crowdsale is active, by the crowdsale owner’s address sending additional Transaction type 51 messages with: * a Currency Identifier Desired value, * the Number Properties per Unit Invested value for the specified Currency Identifier Desired, and * all other fields null (\0) or zero (0)
The same validity requirements must apply to these fields as applied to the crowdsale’s original Transaction type 51 message. The values in the other data fields of the new message must be null (\0) or zero (0). The values from those fields in the crowdsale’s original Transaction type 51 message, including Early Bird Bonus %/Week and Percentage for issuer, apply to all accepted currencies for the crowdsale.
While the crowdsale is active, the crowdsale owner’s address must be able to change the Number Properties per Unit Invested value by sending a new Transaction type 51 message with the new value. The new value must apply to participation in this crowdsale following the change. A crowdsale must be able to stop accepting coins in a Currency Identifier, temporarily or permanently, by specifying zero (0) for the Number Properties per Unit Invested. There must be no limit to the number of Transaction type 51 messages that can be applied to an active crowdsale. These messages must be able to enable, change or stop acceptance of any valid currency id.
Participating in a crowdsale is accomplished by sending coins of one of the desired currencies to the crowdsale owner’s address with the Simple Send transaction or a bitcoin Send transaction if the crowdsale accepts bitcoins (currency id 0) for purchases. Use multiple Sends to make multiple purchases in the crowdsale. In order to participate in the crowdsale, the currency id must match one of the “Currency identifier desired” values being accepted in the crowdsale and the Send message must be confirmed before any of the following conditions occurs: * there is a block with a blocktime greater than or equal to the crowdsale’s “Deadline” value * the crowdsale is manually closed * the maximum number of tokens that can be issued by a crowdsale has been generated (92,233,720,368.54775807 divisible tokens or 9,223,372,036,854,775,807 indivisible tokens, see field Number of Coins).
The blocktime of the Send message must be strictly less than the “Deadline” value in order to participate in the crowdsale.
Note: It is possible for a bitcoin block to have a blocktime earlier than a previous block. Once a crowdsale is closed for any reason, a subsequent Send must not be treated as participating in that crowdsale regardless of the blocktime associated with the Send.
For divisible properties, the sending address will be credited with the number of tokens calculated as the corresponding “Number Properties per unit invested” value multiplied by the number of coins (units) specified in the Send message, plus that number of tokens multiplied by the percentage based on the “Early Bird Bonus %/Week” value, to eight decimal places.
For indivisible properties, the sending address will be credited with the number of tokens calculated as the corresponding “Number Properties per unit invested” value multiplied by the number of coins (units) specified in the Send message, plus that number of tokens multiplied by the percentage based on the “Early Bird Bonus %/Week” value, rounded down to an integer number of tokens (with no fractional portion).
The aggregate number of tokens credited in a crowdsale is limited by the maximum allowable number of tokens in a Smart Property (see Number of coins). The UI should accurately display the number of tokens that will be credited to the sending address.
Note these important details:
-
If the Send transaction is not in one of the currencies being accepted, no purchase will be made and no tokens will be credited to the sending address, but the Send itself will complete if it is valid.
-
Payments will be applied to whatever crowdsale is active at the time of confirmation if the currency specified matches one of the crowdsale’s “Currency identifier desired”.
-
If the Send transaction is confirmed after the crowdsale is closed or if for any other reason no crowdsale is active, no purchase will be made and no tokens will be credited to the sending address, but the Send itself will complete.
-
Tokens credited to the sending address and the issuer address are immediately added to the available balance belonging to the respective addresses and can be spent or otherwise used by that address.
-
The funds received are immediately added to the available balance belonging to the crowdsale owner’s address and can be spent or otherwise used by that address.
-
When accepting currencies other than OMNI, a small fee will be deducted (see fees above) from the coins issued to crowdsale participants.
Say that having created your “Quantum Miner” smart property (which was assigned property ID #8) you now want it to show up higher in the list of properties. You decide to spend 3 OMNI to promote your smart property so that it is displayed higher in the list than all the spam/scam/experimental properties. Doing so takes 13 bytes:
-
Transaction type = 52
-
Ecosystem = 1 for a property within the OMNI ecosystem (as opposed to Test OMNI)
-
Property ID = 8
-
Number of OMNI = 300,000,000 (3.00000000 OMNI)
This transaction permanently destroys OMNI in exchange for favorable placement of this property in the default sort-ordering of properties on every UI. Protocol parsers accumulate all promotions of a property (which can be done by any address which has OMNI), with newer promotions being worth more than older promotions.
To accomplish this time-weighting, a promotion is worth (# OMNI spent) * 3^(years since exodus), where “years since exodus” is the number of years (including partial years) since the OMNI crowdsale ended on September 1st 2013, and thus new promotions are always worth 3x as much as year-old promotions and 9x as much as two-year-old promotions if the same number of OMNI were spent on each.
UIs will probably also choose to offer other sort orderings, such as by transaction volume, removing the need to continually promote a property once it is well-established. Categories and subcategories should be similarly sorted, using the sum of the promotions they contain by default with other sorting available such as the sum of the transaction volumes. UI designers should expect the number of spammy properties, categories, and sub-categories to be quite large, so intelligent sorting will be important.
In the Test OMNI ecosystem, test MSC are destroyed instead of real MSC.
Since crowdsales are generally open-ended, it leaves the potential that raising far more funds than intended could dilute the value of tokens sold early in the crowdsale to an unacceptable level. To prevent this, the Issuer on Record address for the property can issue a command to close the crowdsale manually. This action does not cause the early bird bonus percentage to be recalculated for existing purchases.
It is invalid to attempt to close a crowdsale that is not active. Closing an active crowdsale requires 8 bytes. For example, to close the crowdsale that was assigned Property ID 9, the transaction message is:
Field | Type | Example |
---|---|---|
Transaction version |
0 |
|
Transaction type |
53 |
|
Property ID |
9 |
Note that attempts to participate in a closed crowdsale will result in no investment in that crowdsale and no tokens from that crowdsale will be credited as a result of these attempts. See Participating in a Crowdsale for details.
This feature is supported since block number 323230.
Description: Transaction type 54 is used to create a new Smart Property whose token pool is actively managed by the address that creates the property.
Creating a managed smart property does not automatically grant any tokens to the address that broadcasts the transaction. Instead two additional transaction types exist to actively manage the size of the token pool: Grant Tokens and Revoke Tokens.
In addition to the validity constraints for each message field type, the following conditions must be met in order for the transaction to be valid: * “Previous Property ID” must be 0 when “Property Type” indicates a new property * When “Property Type” indicates a property is being replaced or appended, “Previous Property ID” must be a currency ID created by the address * “Property Name” must not be blank or null
Using the “Quantum Miner” details from the fixed token issuance, the transaction fields would be 72 bytes:
Field | Type | Example |
---|---|---|
Transaction version |
0 |
|
Transaction type |
54 |
|
Ecosystem |
1 (OMNI ecosystem) |
|
Property Type |
1 (new Indivisible tokens) |
|
Previous Property ID |
0 (for a new smart property) |
|
Property Category |
“Companies\0” (10 bytes) |
|
Property Subcategory |
“Bitcoin Mining\0” (15 bytes) |
|
Property Name |
“Quantum Miner\0” (14 bytes) |
|
Property URL |
“tinyurl.com/kwejgoig\0” (21 bytes) |
|
Property Data |
“\0” (1 byte) |
This feature is supported since block number 323230.
Description: Properties issued with a Property with Managed Number of Tokens transaction have no tokens by default. After issuance, tokens may be added to the balance of a referenced address by broadcasting a this type of transaction.
It is invalid to attempt to grant tokens on any property that was not broadcast as a Property with Managed Number of Tokens.
It is invalid to attempt to broadcast a token grant on any property from an address other than the Issuer on Record address for the property.
It is invalid to attempt to grant tokens on any property that would increase the total number of tokens in circulation for that property to more than the maximum number of coins for a smart property, see Number of coins.
Say that you have a smart property whose ID is 8 and you have just reached a fundraising milestone for the project related to that smart property. If you wanted to grant 1,000 tokens into your address as a result of this milestone so that you could distribute them, it would be 40 bytes:
Field | Type | Example |
---|---|---|
Transaction version |
0 |
|
Transaction type |
55 |
|
Property ID |
8 |
|
Number Properties |
1,000 |
|
Memo (Optional) |
“First Milestone Reached!” (24 byte) |
This feature is supported since block number 323230.
Description: Properties issued with a Property with Managed Number of Tokens transaction may have tokens voluntarily revoked from the balance of any address that has a positive token balance.
It is invalid to attempt to revoke tokens on any property that was not broadcast as a Property with Managed Number of Tokens.
It is invalid to attempt to broadcast a token revoke on any property for an address other than the address that broadcasts the revoke transaction.
It is invalid to attempt to revoke any amount of tokens in excess of the number owned and available by the address that broadcasts the transaction.
Say that your project is finished and you want to start burning tokens in exchange for the rewards your promised early backers. If you wanted to revoke 1,000 tokens from your address in exchange for shipping a reward it would be 58 bytes:
Field | Type | Example |
---|---|---|
Transaction version |
0 |
|
Transaction type |
56 |
|
Property ID |
8 |
|
Number Properties |
1,000 |
|
Memo |
“Redemption of tokens for Bob, Thanks Bob!” (42 byte) |
The Omni Protocol provides support for a limited number of administrative tasks regarding Smart Properties. Administrative actions are permitted only by the Issuer on Record (issuer) which is implicitly recognized as the address which originally broadcast the transaction that reserved the currency ID of the Smart Property in question until explicitly changed. The transactions which create an implicit Issuer on Record are: * 50: Create a Property with fixed number of tokens * 51: Create a Property via Crowdsale with Variable number of Tokens * 54: Create a Managed Property with Grants and Revocations
Description: Issuers on Record may broadcast a transaction which will explicitly change the Issuer on Record for future transactions involving a Smart Property. For future transactions the Issuer on Record will be the reference address used in this transaction.
It is invalid to attempt to broadcast a Change of Issuer on Record on a given property from an address other than the address that is the currently recognized Issuer on Record.
It is invalid to attempt to broadcast a Change of Issuer on Record without specifying a Reference Address in the transaction.
Say that you wanted to transfer the Issuer on Record status to another address on a property for which you control the current Issuer on Record address. The transaction would be 8 bytes:
Field | Type | Example |
---|---|---|
Transaction version |
0 |
|
Transaction type |
70 |
|
Property ID |
13 |
Occasionally the bitcoin blockchain experiences a “reorg”, when the current longest chain is replaced by another longer chain. Sometimes this results in recent transactions changing their order, or which transactions are included.
The Omni Protocol depends heavily on the order in which transactions appear in the blockchain. Even transactions in the same block can have different meaning or validity depending on the order in which they are recorded. Consequently, wallets and other blockchain parsers which also parse Omni Protocol transactions need to detect these reorganizations and reparse the affected blocks, changing Omni Protocol balances according to the the new ordering of transactions.
Initially, a reorganization could trigger a “naive” reparse, starting from the beginning and parsing all transactions in the history of the Omni Protocol. Eventually, parsers should become more sophisticated and should keep checkpoints with all relevant Omni Protocol Data written to disk at block milestones, so that they can start from the most recent unaffected checkpoint when a reorg event is detected.
The most important thing is that reorgs ARE detected. If an implementation does not contain code to react to reorgs, it could lose consensus with the other implementations, effectively forking the Omni Protocol until the problem is noticed and the affected implementation is manually reset.
Also, in many cases a user may wish to do something with OMNI recently sent to them or otherwise affected by a recent transaction. Where possible, Omni-aware wallets should re-use bitcoins from the previous transactions in subsequent transactions which are dependent on the earlier transactions. In this way, if the earlier transaction is invalidated (by a reorg), the dependent transaction will also be invalidated.
There are two broad categories of transactions which have no fees (other than fees charged by the bitcoin protocol layer):
-
All tokens in the OMNI protocol can be sent (using simple send) with no fees.
-
Any transaction which directly uses OMNI also has no fees.
-
Creating a property does not carry a fee (we don’t want barriers to entry)
-
Property management (changing ownership, issuing new tokens, revoking tokens, etc) does not carry a fee (integral to some business models, which we don’t want to discourage)
Here are some examples of transactions which have no fee:
-
Sending MaidsafeCoin using simple send
-
Buying and selling MaidsafeCoin using OMNI on the distributed exchange
-
Placing a bet denominated in OMNI
-
Paying OMNI to all OMNI holders (pay to owners)
-
Paying OMNI to purchase a physical good on the distributed e-commerce platform
Transactions which do not meet this criteria pay a flat 0.1% fee, deducted from whatever currency or property is being used (rounded to the nearest representable amount).
Here are some examples of transactions which would pay a 0.1% fee:
-
Buying and selling MaidsafeCoins with USDCoins on the distributed exchange
-
Placing a bet denominated in USDCoins
-
Paying MaidsafeCoin to all MaidsafeCoin holders (pay to owners)
-
Paying USDCoin to purchase a physical good on the distributed e-commerce platform
Fees are used to automatically purchase and destroy OMNI on the distributed exchange. In some cases, fees may round down to zero, or round up as high as 0.2%. For example, there is never a fee as long as the number of traded units is less than 500 (0.00000500 for divisible currencies), because 0.1% of 499 rounds to zero, while 0.1% of 500 rounds up to 1. Similarly, 0.1% of 1499 rounds down to 1, and so on.
Here’s an example:
Peter bets against Paul about what the price of Gold will do over the next 3 days. The bet is denominated in USDCoin, and is worth $10,000. When the bet is settled, 0.1% of the bet amount is deducted ($10). That $10 is automatically applied to purchase OMNI on the OMNI/USDCoin distributed exchange, using a “market” order. If at least 0.00000001 OMNI is not available for purchase for $10, a limit order is created for 0.00000001 OMNI for $10. Once the order has been filled, the OMNI are destroyed, gone forever.
Notice at no point does Peter or Paul have to own any OMNI, yet their bet automatically results in the purchase and destruction of OMNI, which benefits everyone who owns OMNI.
When a transaction has other percentage-of-total calculations (for instance, the distributed exchange liquidity bonus), those calculations are based on the total before any fees are deducted. For instance, the 0.3% liquidity bonus and 0.1% fee would be calculated from the same total - they do not affect each other.
You can read more about this fee structure on our blog: https://blog.omni.foundation/2014/06/11/mastercoin-is-for-burning/
Not all features described in this document are active by default. Each feature will be unlocked on a certain block once it’s deemed stable. Only Test Omni transactions will be allowed if a feature is not unlocked yet. All other messages will be invalidated. The only exception to this rule is the Simple Send message, this has been enabled since Exodus.
-
OMNI/bitcoin distributed exchange features are unlocked as of block #290630
-
Smart property features are unlocked as of block #297110
-
Savings wallets and rate-limited wallets are unlocked as of block # (TBD)
-
Data feeds and simple betting are unlocked as of block # (TBD)
-
Contract-for-difference bets are unlocked as of block # (TBD)
-
Distributed e-commerce features are unlocked as of block # (TBD)
-
Escrow-backed currencies are unlocked as of block # (TBD)
-
Managed Token-pool Smart Property features are unlocked as of block #323230
-
Pay-to-script-hash address support is unlocked as of block #322000
-
Send To Owners transaction type is unlocked as of block #342650
- Exodus Address
-
1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P
. A very special Bitcoin address that is used by Omni for multiple purposes. - Omni
-
When written with only the first letter capitalized, Omni refers to the protocol, the ecosystem, or the Omni Foundation.
- OMNI
-
When written in all-uppercase, OMNI refers to the OMNI token (the Omni smart property with ID of
1
) - Omni Consensus
-
The current state of all accounts in the Omni Layer.
-
[satoshi] Nakamoto, Satoshi, "Bitcoin: A Peer-to-Peer Electronic Cash System", 2008, https://bitcoin.org/bitcoin.pdf