CIP: 16 Title: Scheduled Dividends Author: Dan Anderson Discussions-To: https://counterpartytalk.org/t/cip-proposal-scheduled-distributions/4449 Status: Draft Type: Standards Track Created: 2018-03-12
Allow dividends to be scheduled to activate on locked assets, by defining future block height and escrowing funds.
Mirroring the approach used by orders and order expirations, this CIP extends dividends to include an optional activation index. As part of this improvement, a dividend_activations table will be utilized, as well as, a new dividend status equal to 'pending.' These three changes, combined with new validation rules and message encoding, constitute this feature.
Effects of CIP
After this change, when an activation index is not provided, dividends will be distributed, as they have been, immediately. However, when an activation index is provided, the quantity needed to fund that distribution will become escrowed and those funds will not be distributed until the current block height equals the given activation index.
Important to note: Unlike orders, which can be canceled before their expiration index, scheduled dividends cannot be canceled. Also important to note: Recipients of the scheduled dividend will be calculated at the time of activation, not before.
XCP Gas Fees
At present, dividends cost 0.0002 XCP per recipient
fee = int(0.0002 * config.UNIT * holder_count). In the case of scheduled dividends, the number of future asset holders is unknown.
This CIP proposes using the current holder count, at time of scheduling, with a 0.1 XCP minimum to avoid gaming fees. Example: Scheduling a dividend when there is one asset holder, knowing there will be hundreds at activation.
if holder_count <= 500: fee = int(0.01 * config.UNIT) else: fee = int(0.0002 * config.UNIT * holder_count)
In order to ensure that a scheduled dividend is truly and fully funded by the escrowed funds, it is necessary that the asset receiving the dividend be locked. Otherwise, new issuances made between the time of scheduling and activation of a dividend can result in insufficient funding and a bad user experience. Although, this could change with time and education.
When validating assets, in addition to existing checks, the given asset should be checked to ensure:
- The asset has been locked.
Normal dividends exclude the source address, as it is unncessary to debit their balance just to immediately credit it again. Their share of a dividend is implicit and is just the amount left in their account after paying other holders. Scheduled dividends will not exclude the source address, as it is necessary, in this instance.
New consensus variables known as
MAX_ACTIVATION will be used to instate an upper and lower limit on dividend lockup times. The corresponding value for order expirations is
MAX_EXPIRATION = 4 * 2016 # Two months.
This CIP defines
MIN_ACTIVATION = 144 # One day and
MAX_ACTIVATION = 210000 # Four years.
Imposing a one day minimum helps avoid the edge case where a transaction confirms after the scheduled activation index, which would act no differently than a normal dividend, for potentially a higher fee gas fee. And having a reasonably distant upper limit keeps scheduled dividends from imposing too much cost on the network.
When validating activation indexes, the given value should be checked to ensure:
- The activation index is an integer.
- The activation index is unsigned.
- The activation index is a future block height.
- The difference between the current block height and the activation index is not less than
- The difference between the current block height and the activation index is not greater than
To store the activation index, tables need to be altered and created as follows (closely follows order expirations)...
---Pseudocode--- ALTER TABLE dividends ADD COLUMN activate_index INTEGER DEFAULT 0 CREATE INDEX IF NOT EXISTS activate_idx ON dividends (activate_index, status) CREATE TABLE IF NOT EXISTS dividend_activations dividend_index INTEGER PRIMARY KEY, dividend_hash TEXT UNIQUE, source TEXT, block_index INTEGER, FOREIGN KEY (block_index) REFERENCES blocks(block_index), CREATE INDEX IF NOT EXISTS block_index_idx ON dividend_activations (block_index) CREATE INDEX IF NOT EXISTS source_idx ON dividend_activations (source)
After this change, dividends can be differentiated from scheduled dividends by using the dividend_activations table, looking for the 'pending' status, or looking for the presence of an activation index.
At present, there are two encoding formats defined...
FORMAT_1 = '>QQ' LENGTH_1 = 8 + 8 FORMAT_2 = '>QQQ' LENGTH_2 = 8 + 8 + 8
This CIP would created a third
FORMAT_3 such that...
FORMAT_3 = '>QQQH' LENGTH_3 = 8 + 8 + 8 + 2
In order to accomodate the inclusion of an activation index.
Having scheduled dividends will increase the usefulness of Counterparty assets to asset issuers.
This CIP will make dividends:
- Trustless - Funds are escrowed and dividends cannot be canceled.
- Timely - Precise block heights, not possible relying on fee market alone.
- Convenient - Many reasons to want to, "Set and Forget," dividends.
- Fee Efficient - It may be the case that schedulers can avoid higher fees later.
Possible use cases include:
- Issuance Lockup
- Founder Vesting
- Automated Distributions
Much of the rationale has been included in-line, above. But the overall approach is to mirror orders and order expirations, which escrow value for a period of time, but in a different direction. "Good until" versus "Not good before".
This change will require a hardfork upgrade to the protocol. This change is not possible as a soft fork as nodes may interpret scheduled dividends differently. Not updating balances in some cases and updating balances too soon in others.
There is not yet a reference implentation for this CIP as its status is currently that of DRAFT. However, some initial rough work has been done here: https://github.com/droplister/counterparty-lib/tree/scheduled_dividends.
This document is placed in the public domain.