Accounts may contain funds that are available to send according to a vesting schedule.
Time-locked accounts are useful to delay the availability of funds. Such accounts have been used in other cryptocurrencies to implement features such as payment channels. The locking feature can be used to create incentives; if the account holder performs a certain action, the account can be funded so that the locked funds are released.
Vesting schedules are a generalization of the time-locking mechanism, where funds become increasingly available over time. There are two times specified, one that indicates when some amount of funds becomes available to send, and another, later time that specifies when all funds become available to send. The amount available to send increases between those two times.
Accounts may have no timing restrictions, have a time lock, or a
vesting schedule. In Coda, the type Account.t
is a record type with
several fields. An additional field timing
could contain an element
of a sum type with three alternatives: Untimed
and Timed
.
Untimed
means there are no time restrictions on sending funds.
A Timed
value contains an initial_minimum_balance
, cliff
time, a vesting_period
time, and a vesting_increment
.
Until the cliff time has passed, the account can send only funds from
its balance that are in excess of the initial minimum balance. After the
cliff time has passed, more funds are available, by calculating a current
minimum balance which decreases over time. The minimum balance decreases
by the vesting increment for each vesting period:
current_minimum_balance =
if global_slot < cliff_time
then
initial_minimum_balance
else
max 0 (initial_minimum_balance - ((global_slot - cliff_time) / vesting_period) * vesting_increment))
(where / is integer division).
If a transaction amount would make the account balance less than the current minimum, the transaction is disallowed.
Nothing prevents sending funds to timed accounts. When timed accounts are created, the balance must be at least the initial minimum balance. The account can receive additional funds, and funds can be spent, as long as the minimum balance invariant is maintained.
A time-locked account time, can be created by using a vesting increment equal to the initial minimum balance and a vesting period of one slot. (In the calculation above, using a vesting period of zero would result in a division by zero.)
The restrictions on sending funds need to be enforced in the transaction SNARK and out-of-SNARK. If the restrictions are violated, an error occurs.
For the out-of-SNARK transaction, the relevant code location to
enforce the restrictions appears to be in
Transaction_logic.apply_user_command_unchecked
.
For the in-SNARK transaction, the restriction would be enforced in
Transaction_snark.apply_tagged_transaction
.
Adding this feature makes the account data slightly larger, slows down the validation of transactions, and makes the implementation a bit more complex. Those considerations should be weighed against the utility of the feature to users.
Instead of using a global slot time, we could use block height. The global slot time is available via the protocol state, which will be made available to transactions.
Bitcoin uses a block field nLockTime
, denoting a block time, which can be used to
time-lock individual transactions. There are many articles about time-locked accounts for
Ethereum by programming smart contracts. See, for example:
https://medium.com/bitfwd/time-locked-wallets-an-introduction-to-ethereum-smart-contracts-3dfccac0673c.
Beyond cryptocurrencies, vesting of benefits is a well-established idea in employment.
Do timed accounts interact with staking in any way?