module SET-BALANCE
imports INT
imports DOMAINS
imports COLLECTIONS
configuration
<set-balance>
<k> $ACTION:Action </k>
<now> 0 </now>
<events> .List </events>
<return-value> .Result </return-value>
<call-stack> .List </call-stack>
<existentialDeposit> 0 </existentialDeposit>
<creationFee> 0 </creationFee>
<transferFee> 0 </transferFee>
<totalIssuance> 0 </totalIssuance>
<accounts>
<account multiplicity="*" type="Map">
<accountID> .AccountId:AccountId </accountID>
<freeBalance> 0 </freeBalance>
<reservedBalance> 0 </reservedBalance>
<vestingBalance> 0 </vestingBalance>
<startingBlock> 0 </startingBlock>
<perBlock> 0 </perBlock>
<nonce> .Nonce </nonce>
<locks> .Set </locks>
</account>
</accounts>
</set-balance>
- An
AccountId
is anInt
. - An
Origin
is anAccountId
,Root
, orNone
. - A
Nonce
is an optionalInt
. - An
Event
records some happenning.
syntax AccountId ::= ".AccountId" | Int
// ---------------------------------------
syntax Origin ::= AccountId | ".Root" | ".None"
// -----------------------------------------------
syntax Nonce ::= ".Nonce" | Int
// -------------------------------
syntax Event ::= DustEvent ( Int )
// ----------------------------------
Some predicates which help specifying behavior:
#inWidth
: Specify that a given number is in some bitwidth.
syntax Bool ::= #inWidth(Int, Int) [function, functional]
// ---------------------------------------------------------
rule #inWidth(N, M) => 0 <=Int M andBool M <Int (2 ^Int N)
A Result
is the return value of an execution step.
AccountKilled
indicates that the free balance goes below the existential threshold.Updated
indicates that an account was updated successfully.
syntax Result ::= ".Result" | "AccountKilled" | "Updated"
// ---------------------------------------------------------
Retrieves the total balance of an account. This includes both the free and reserved balances.
syntax Int ::= "total_balance" "(" AccountId ")" [function, functional]
// -----------------------------------------------------------------------
rule total_balance(WHO) => free_balance(WHO) +Int reserved_balance(WHO)
Gets the free balance of an account.
Other than when this module is executing, this will never be strictly between
EXISTENTIAL_DEPOSIT
and zero.
syntax Int ::= "free_balance" "(" AccountId ")" [function, functional]
// ----------------------------------------------------------------------
rule free_balance(_) => 0 [owise]
rule [[ free_balance(WHO) => FREE_BALANCE ]]
<account>
<accountID> WHO </accountID>
<freeBalance> FREE_BALANCE </freeBalance>
...
</account>
Gets the reserved balance of an account.
Other than when this module is executing, this will never be strictly between
EXISTENTIAL_DEPOSIT
and zero.
syntax Int ::= "reserved_balance" "(" AccountId ")" [function, functional]
// --------------------------------------------------------------------------
rule reserved_balance(_) => 0 [owise]
rule [[ reserved_balance(WHO) => FREE_BALANCE ]]
<account>
<accountID> WHO </accountID>
<reservedBalance> FREE_BALANCE </reservedBalance>
...
</account>
Determines if an account’s free balance is over the value provided. This is often used to determine if an account has enough balance to cover a potential slash, hence the name.
syntax Bool ::= "can_slash" "(" AccountId "," Int ")" [function, functional]
// ----------------------------------------------------------------------------
rule can_slash(_, _) => false
rule [[ can_slash(WHO, AMOUNT) => FREE_BALANCE >=Int AMOUNT ]]
<account>
<accountID> WHO </accountID>
<freeBalance> FREE_BALANCE </freeBalance>
...
</account>
Retrieves the total outstanding amount of currency outstanding. This will always be equal to the sum of all free and reserved balances in all active accounts, except when the balances module is executing.
syntax Int ::= "total_issuance" [function, functional]
// ------------------------------------------------------
rule [[ total_issuance => TOTAL_ISSUANCE ]]
<totalIssuance> TOTAL_ISSUANCE </totalIssuance>
Issues currency, creating an imbalance.
This is not specified, since these semantics do not include the concept of an imbalance. Without the concept of destructors and move semantics, it would be almost impossible to use correctly.
Burns currency.
This is not part of the semantics for the same reason burn
is not.
An Action
is an execution step (or the result of an execution step).
An EntryAction
is an Action
that can be invoked externally.
A Result
is considered an Action
, as is an EntryAction
.
syntax Action ::= Result | EntryAction
// --------------------------------------
syntax Bool ::= "account_exists" "(" AccountId ")" [function, functional]
// -------------------------------------------------------------------------
rule account_exists(_) => false [owise]
rule [[ account_exists(WHO) => true ]]
<account> <accountID> WHO </accountID> ... </account>
syntax Action ::= "create_account" "(" AccountId ")"
// ----------------------------------------------------
rule <k> create_account(WHO) => . ... </k>
<accounts> ( .Bag => <account> <accountID> WHO </accountID> ... </account> ) ... </accounts>
- Updates an accounts balance if the new balance is above the existential threshold.
- Kills the account if the balance goes below the existential threshold and the reserved balance is non-zero.
- Reaps the account if the balance goes below the existential threshold and the reserved balance is zero.
syntax Action ::= "set_free_balance" "(" AccountId "," Int ")"
// --------------------------------------------------------------
rule <k> (. => create_account(WHO)) ~> set_free_balance(WHO, _) ... </k>
requires notBool account_exists(WHO)
rule [free-account-updated]:
<k> set_free_balance(WHO, BALANCE) => . ... </k>
<existentialDeposit> EXISTENTIAL_DEPOSIT </existentialDeposit>
<account>
<accountID> WHO </accountID>
<freeBalance> _ => BALANCE </freeBalance>
...
</account>
requires EXISTENTIAL_DEPOSIT <=Int BALANCE
rule [free-account-killed]:
<k> set_free_balance(WHO, BALANCE) => . ... </k>
<events> ... (.List => ListItem(DustEvent(FREE_BALANCE))) </events>
<existentialDeposit> EXISTENTIAL_DEPOSIT </existentialDeposit>
<totalIssuance> TOTAL_ISSUANCE => TOTAL_ISSUANCE -Int BALANCE </totalIssuance>
<account>
<accountID> WHO </accountID>
<nonce> _ => .Nonce </nonce>
<freeBalance> FREE_BALANCE => 0 </freeBalance>
<reservedBalance> RESERVED_BALANCE </reservedBalance>
...
</account>
requires BALANCE <Int EXISTENTIAL_DEPOSIT
andBool 0 <Int RESERVED_BALANCE
rule [free-account-reaped]:
<k> set_free_balance(WHO, BALANCE) => . ... </k>
<events> ... (.List => ListItem(DustEvent(FREE_BALANCE))) </events>
<existentialDeposit> EXISTENTIAL_DEPOSIT </existentialDeposit>
<totalIssuance> TOTAL_ISSUANCE => TOTAL_ISSUANCE -Int BALANCE </totalIssuance>
<accounts>
( <account>
<accountID> WHO </accountID>
<freeBalance> FREE_BALANCE </freeBalance>
<reservedBalance> 0 </reservedBalance>
...
</account>
=> .Bag
)
...
</accounts>
requires BALANCE <Int EXISTENTIAL_DEPOSIT
- Updates an accounts balance if the new balance is above the existential threshold.
- Kills the account if the balance goes below the existential threshold and the free balance is non-zero.
- Reaps the account if the balance goes below the existential threshold and the free balance is zero.
syntax Action ::= "set_reserved_balance" "(" AccountId "," Int ")"
// ------------------------------------------------------------------
rule <k> (. => create_account(WHO)) ~> set_reserved_balance(WHO, _) ... </k>
requires notBool account_exists(WHO)
rule [reserved-account-updated]:
<k> set_reserved_balance(WHO, BALANCE) => . ... </k>
<existentialDeposit> EXISTENTIAL_DEPOSIT </existentialDeposit>
<account>
<accountID> WHO </accountID>
<reservedBalance> _ => BALANCE </reservedBalance>
...
</account>
requires EXISTENTIAL_DEPOSIT <=Int BALANCE
rule [reserved-account-killed]:
<k> set_reserved_balance(WHO, BALANCE) => . ... </k>
<events> ... (.List => ListItem(DustEvent(RESERVED_BALANCE))) </events>
<existentialDeposit> EXISTENTIAL_DEPOSIT </existentialDeposit>
<totalIssuance> TOTAL_ISSUANCE => TOTAL_ISSUANCE -Int BALANCE </totalIssuance>
<account>
<accountID> WHO </accountID>
<nonce> _ => .Nonce </nonce>
<freeBalance> FREE_BALANCE </freeBalance>
<reservedBalance> RESERVED_BALANCE => 0 </reservedBalance>
...
</account>
requires BALANCE <Int EXISTENTIAL_DEPOSIT
andBool 0 <Int FREE_BALANCE
rule [reserved-account-reaped]:
<k> set_reserved_balance(WHO, BALANCE) => . ... </k>
<events> ... (.List => ListItem(DustEvent(RESERVED_BALANCE))) </events>
<existentialDeposit> EXISTENTIAL_DEPOSIT </existentialDeposit>
<totalIssuance> TOTAL_ISSUANCE => TOTAL_ISSUANCE -Int BALANCE </totalIssuance>
<accounts>
( <account>
<accountID> WHO </accountID>
<freeBalance> 0 </freeBalance>
<reservedBalance> RESERVED_BALANCE </reservedBalance>
...
</account>
=> .Bag
)
...
</accounts>
requires BALANCE <Int EXISTENTIAL_DEPOSIT
- Sets the new free balance
- Creates suitible imbalances (both positive and negative).
- Calls
set_free_balance
with the new free balance. - Calls
set_reserved_balance
with the new reserved balance.
syntax EntryAction ::= "set_balance" "(" AccountId "," AccountId "," Int "," Int ")"
// ------------------------------------------------------------------------------------
rule [balance-set]:
<k> set_balance(Root, WHO, FREE_BALANCE, RESERVED_BALANCE)
=> set_balance_free(WHO, FREE_BALANCE)
~> set_balance_reserved(WHO, RESERVED_BALANCE)
...
</k>
Helpers for calling set_free_balance
and set_reserved_balance
.
- Sets the new free balance
- Emits an imbalance event
- Helper function for
set_balance
syntax Action ::= "set_balance_free" "(" AccountId "," Int ")"
syntax Action ::= "set_balance_reserved" "(" AccountId "," Int ")"
// ------------------------------------------------------------------
rule [balance-set-free]:
<k> set_balance_free(WHO, FREE_BALANCE') => set_free_balance(WHO, FREE_BALANCE') ... </k>
<totalIssuance> ISSUANCE => ISSUANCE +Int (FREE_BALANCE' -Int free_balance(WHO)) </totalIssuance>
requires #inWidth(96, ISSUANCE +Int (FREE_BALANCE' -Int free_balance(WHO)))
rule [balance-set-reserved]:
<k> set_balance_reserved(WHO, RESERVED_BALANCE') => set_reserved_balance(WHO, RESERVED_BALANCE') ... </k>
<totalIssuance> ISSUANCE => ISSUANCE +Int (RESERVED_BALANCE' -Int reserved_balance(WHO)) </totalIssuance>
requires #inWidth(96, ISSUANCE +Int (RESERVED_BALANCE' -Int reserved_balance(WHO)))
Transfer some liquid free balance to another account.
transfer
will set the FreeBalance
of the sender and receiver.
It will decrease the total issuance of the system by the TransferFee
.
If the sender's account is below the existential deposit as a result
of the transfer, the account will be reaped.
The dispatch origin for this call must be Signed
by the transactor.
syntax ExistenceRequirement ::= "AllowDeath"
| "KeepAlive"
syntax EntryAction ::= transfer(Origin, AccountId, Int)
| "transfer_keep_alive" "(" Origin "," AccountId "," Int ")"
// ---------------------------------------------------------------------------------
syntax Action ::= rawTransfer(AccountId, AccountId, Int, ExistenceRequirement)
// ------------------------------------------------------------------------------
rule [transfer-to-raw]:
<k> transfer(ORIGIN:AccountId, DESTINATION, AMOUNT)
=> rawTransfer(ORIGIN, DESTINATION, AMOUNT, AllowDeath)
...
</k>
rule [transfer-keep-alive]:
<k> transfer_keep_alive(ORIGIN:AccountId, DESTINATION, AMOUNT)
=> rawTransfer(ORIGIN, DESTINATION, AMOUNT, KeepAlive)
...
</k>
rule <k> (. => create_account(DESTINATION)) ~> rawTransfer(ORIGIN, DESTINATION, _, _) ... </k>
requires account_exists(ORIGIN)
andBool notBool account_exists(DESTINATION)
rule [transfer-self]:
<k> rawTransfer(ORIGIN:AccountId, ORIGIN, _, _) => . ... </k>
requires account_exists(ORIGIN)
rule [transfer-existing-account]:
<k> rawTransfer(ORIGIN, DESTINATION, AMOUNT, EXISTENCE_REQUIREMENT)
=> set_free_balance(ORIGIN, SOURCE_BALANCE -Int AMOUNT -Int FEE)
~> set_free_balance(DESTINATION, DESTINATION_BALANCE +Int AMOUNT)
...
</k>
<totalIssuance> ISSUANCE => ISSUANCE -Int FEE </totalIssuance>
<existentialDeposit> EXISTENTIAL_DEPOSIT </existentialDeposit>
<transferFee> FEE </transferFee>
<accounts>
<account>
<accountID> ORIGIN </accountID>
<freeBalance> SOURCE_BALANCE </freeBalance>
...
</account>
<account>
<accountID> DESTINATION </accountID>
<freeBalance> DESTINATION_BALANCE </freeBalance>
...
</account>
</accounts>
requires ORIGIN =/=K DESTINATION
andBool DESTINATION_BALANCE >Int 0
andBool SOURCE_BALANCE >=Int (AMOUNT +Int FEE)
andBool ensure_can_withdraw(ORIGIN, Transfer, SOURCE_BALANCE -Int AMOUNT -Int FEE)
andBool (EXISTENCE_REQUIREMENT ==K AllowDeath orBool SOURCE_BALANCE -Int AMOUNT -Int FEE >Int EXISTENTIAL_DEPOSIT)
rule [transfer-create-account]:
<k> rawTransfer(ORIGIN:AccountId, DESTINATION, AMOUNT, EXISTENCE_REQUIREMENT)
=> set_free_balance(ORIGIN, SOURCE_BALANCE -Int AMOUNT -Int CREATION_FEE)
~> set_free_balance(DESTINATION, AMOUNT)
...
</k>
<totalIssuance> ISSUANCE => ISSUANCE -Int CREATION_FEE </totalIssuance>
<existentialDeposit> EXISTENTIAL_DEPOSIT </existentialDeposit>
<creationFee> CREATION_FEE </creationFee>
<accounts>
<account>
<accountID> ORIGIN </accountID>
<freeBalance> SOURCE_BALANCE </freeBalance>
...
</account>
<account>
<accountID> DESTINATION </accountID>
<freeBalance> 0 </freeBalance>
<reservedBalance> 0 </reservedBalance>
...
</account>
...
</accounts>
requires ORIGIN =/=K DESTINATION
andBool SOURCE_BALANCE >=Int (AMOUNT +Int CREATION_FEE)
andBool EXISTENTIAL_DEPOSIT <=Int AMOUNT
andBool ensure_can_withdraw(ORIGIN, Transfer, SOURCE_BALANCE -Int AMOUNT -Int CREATION_FEE)
andBool (EXISTENCE_REQUIREMENT ==K AllowDeath orBool SOURCE_BALANCE -Int AMOUNT -Int CREATION_FEE >=Int EXISTENTIAL_DEPOSIT)
Force a transfer from any account to any other account. This can only be done by root.
syntax EntryAction ::= "force_transfer" "(" Origin "," AccountId "," AccountId "," Int ")"
// ------------------------------------------------------------------------------------------
rule [force-transfer]:
<k> force_transfer(.Root, SOURCE, DESTINATION, AMOUNT) => transfer(SOURCE, DESTINATION, AMOUNT) ... </k>
Withdraw funds from an account.
syntax EntryAction ::= withdraw(AccountId, Int, WithdrawReason, ExistenceRequirement)
// -------------------------------------------------------------------------------------
rule [withdraw]: // K really needs where clauses
<k> withdraw(WHO, AMOUNT, REASON, EXISTENCE_REQUIREMENT)
=> withdrawInner(WHO, AMOUNT, AMOUNT -Int free_balance(WHO), REASON, EXISTENCE_REQUIREMENT)
...
</k>
syntax Action ::= withdrawInner(AccountId, Int, Int, WithdrawReason, ExistenceRequirement)
// ------------------------------------------------------------------------------------------
rule [withdrawInner]:
<k> withdrawInner(WHO, AMOUNT, NEW_BALANCE, REASON, EXISTENCE_REQUIREMENT)
=> set_free_balance(WHO, NEW_BALANCE)
...
</k>
<totalIssuance> ISSUANCE => ISSUANCE -Int AMOUNT </totalIssuance>
<existentialDeposit> EXISTENTIAL_DEPOSIT </existentialDeposit>
requires NEW_BALANCE >=Int 0
andBool ensure_can_withdraw(WHO, REASON, NEW_BALANCE)
andBool (EXISTENCE_REQUIREMENT ==K AllowDeath orBool NEW_BALANCE >=Int EXISTENTIAL_DEPOSIT)
Function call and return.
syntax CallFrame ::= frame(continuation: K)
syntax Action ::= call ( Action )
| return ( Result )
// -----------------------------------
rule [call]:
<k> call(Action) ~> CONT => Action </k>
<call-stack> .List => ListItem(frame(CONT)) ... </call-stack>
rule [return]:
<k> return(R) ~> _ => CONT </k>
<return-value> _ => R </return-value>
<call-stack> ListItem(frame(CONT)) => .List ... </call-stack>
rule [return-unit]:
<k> . => CONT </k>
<return-value> _ => .Result </return-value>
<call-stack> ListItem(frame(CONT)) => .List ... </call-stack>
Ensure that a given amount can be withdrawn from an account.
FIXME: we do not account for multiple withdrawl reasons, due to K’s lacking polymorphism.
syntax WithdrawReason ::= "TransactionPayment"
| "Transfer"
| "Reserve"
| "Fee"
| "Tip"
// -------------------------------
syntax Bool ::= "ensure_can_withdraw" "(" AccountId "," WithdrawReason "," Int ")" [function, functional]
// ---------------------------------------------------------------------------------------------------------
rule ensure_can_withdraw(_, _, _) => true [owise]
rule [[ ensure_can_withdraw(WHO, Transfer #Or Reserve, BALANCE) => false ]]
<account>
<accountID> WHO </accountID>
<vestingBalance> VESTING_BALANCE </vestingBalance>
...
</account>
requires VESTING_BALANCE <Int BALANCE
rule [[ ensure_can_withdraw(WHO, REASON, BALANCE) => false ]]
<now> NOW </now>
<account>
<accountID> WHO </accountID>
<locks> ACCOUNT_LOCKS </locks>
...
</account>
requires activeLocks(ACCOUNT_LOCKS, NOW, REASON, BALANCE)
syntax LockID ::= "Election"
| "Staking"
| "Democracy"
| "Phragmen"
// ----------------------------
syntax AccountLock ::= lock ( id: LockID, until: Int, amount: Int, reasons: Set )
// ---------------------------------------------------------------------------------
syntax Bool ::= activeLock (AccountLock, Int, WithdrawReason, Int ) [function]
| activeLocks(Set, Int, WithdrawReason, Int ) [function]
| activeLocks(List, Int, WithdrawReason, Int, Bool) [function, klabel(activeLocksAux)]
// -----------------------------------------------------------------------------------------------------------
rule activeLock(AL, NOW, REASON, BALANCE) => NOW <Int until(AL) andBool BALANCE <Int amount(AL) andBool REASON in reasons(AL)
rule activeLocks(ALS, NOW, REASON, BALANCE) => activeLocks(Set2List(ALS), NOW, REASON, BALANCE, false)
rule activeLocks(.List, _, _, _, RESULT) => RESULT
rule activeLocks((ListItem(AL) => .List) REST, NOW, REASON, BALANCE, RESULT => RESULT orBool activeLock(AL, NOW, REASON, BALANCE))
The first of these is also used by slash
.
slash_reserved
repatriate_reserved
syntax Action ::= "slash_reserved" "(" AccountId "," Int ")"
// ------------------------------------------------------------
rule [slash-reserved]:
<k> slash_reserved(ACCOUNT, AMOUNT)
=> set_reserved_balance(ACCOUNT, maxInt(0, RESERVED_BALANCE -Int AMOUNT))
...
</k>
<accounts>
<account>
<accountID> ACCOUNT </accountID>
<reservedBalance> RESERVED_BALANCE </reservedBalance>
...
</account>
</accounts>
<totalIssuance> TOTAL_ISSUANCE => TOTAL_ISSUANCE -Int minInt(RESERVED_BALANCE, AMOUNT) </totalIssuance>
syntax Action ::= "repatriate_reserved" "(" AccountId "," AccountId "," Int ")"
// -------------------------------------------------------------------------------
rule [repatriate-reserved]:
<k> repatriate_reserved(SLASHED, BENEFICIARY, AMOUNT)
=> set_free_balance(BENEFICIARY, BENEFICIARY_FREE_BALANCE +Int minInt(SLASHED_RESERVED_BALANCE, AMOUNT))
~> set_reserved_balance(SLASHED, SLASHED_RESERVED_BALANCE -Int minInt(SLASHED_RESERVED_BALANCE, AMOUNT))
...
</k>
<accounts>
<account>
<accountID> SLASHED </accountID>
<reservedBalance> SLASHED_RESERVED_BALANCE </reservedBalance>
...
</account>
<account>
<accountID> BENEFICIARY </accountID>
<reservedBalance> BENEFICIARY_RESERVED_BALANCE </reservedBalance>
<freeBalance> BENEFICIARY_FREE_BALANCE </freeBalance>
...
</account>
</accounts>
requires BENEFICIARY_FREE_BALANCE +Int BENEFICIARY_RESERVED_BALANCE >Int 0
andBool SLASHED =/=K BENEFICIARY
rule [repatriate-reserved-same-account]:
<k> repatriate_reserved(SLASHED, SLASHED, AMOUNT) => unreserve(SLASHED, AMOUNT) ... </k>
Used to punish a node for violating the protocol.
syntax EntryAction ::= slash ( AccountId , Int )
// ------------------------------------------------
rule [slash]:
<k> slash(ACCOUNT, AMOUNT) => set_free_balance(ACCOUNT, FREE_BALANCE -Int AMOUNT) ... </k>
<accounts>
<account>
<accountID> ACCOUNT </accountID>
<freeBalance> FREE_BALANCE </freeBalance>
...
</account>
</accounts>
<totalIssuance> TOTAL_ISSUANCE => TOTAL_ISSUANCE -Int AMOUNT </totalIssuance>
requires FREE_BALANCE >=Int AMOUNT
rule [slash-empty-free]:
<k> slash(ACCOUNT, AMOUNT)
=> set_free_balance(ACCOUNT, 0)
~> slash_reserved(ACCOUNT, AMOUNT -Int FREE_BALANCE)
...
</k>
<accounts>
<account>
<accountID> ACCOUNT </accountID>
<freeBalance> FREE_BALANCE </freeBalance>
...
</account>
</accounts>
<totalIssuance> TOTAL_ISSUANCE => TOTAL_ISSUANCE -Int FREE_BALANCE </totalIssuance>
requires FREE_BALANCE <Int AMOUNT
Used to move balance from free to reserved and visa versa.
syntax Action ::= reserve ( AccountId , Int )
// ---------------------------------------------
rule [reserve]:
<k> reserve(ACCOUNT, AMOUNT)
=> set_reserved_balance(ACCOUNT, FREE_BALANCE +Int AMOUNT)
~> set_free_balance(ACCOUNT, FREE_BALANCE -Int AMOUNT)
...
</k>
<accounts>
<account>
<accountID> ACCOUNT </accountID>
<freeBalance> FREE_BALANCE </freeBalance>
<reservedBalance> RESERVED_BALANCE </reservedBalance>
...
</account>
</accounts>
requires FREE_BALANCE >=Int AMOUNT
andBool ensure_can_withdraw(ACCOUNT, Reserve, FREE_BALANCE -Int AMOUNT)
syntax Action ::= unreserve ( AccountId , Int )
// -----------------------------------------------
rule [unreserve]:
<k> unreserve(ACCOUNT, AMOUNT)
=> set_free_balance(ACCOUNT, FREE_BALANCE +Int minInt(AMOUNT, RESERVED_BALANCE))
~> set_reserved_balance(ACCOUNT, FREE_BALANCE -Int minInt(AMOUNT, RESERVED_BALANCE))
...
</k>
<accounts>
<account>
<accountID> ACCOUNT </accountID>
<freeBalance> FREE_BALANCE </freeBalance>
<reservedBalance> RESERVED_BALANCE </reservedBalance>
...
</account>
</accounts>
locked_at
― amount currently lockedvesting_balance
― get the balance that cannot currently be withdrawn.
syntax Int ::= "locked_at" "(" AccountId ")" [function, functional]
// -------------------------------------------------------------------
rule [[ locked_at(WHO) => maxInt(0, VESTING_BALANCE -Int (PER_BLOCK *Int maxInt(0, NOW -Int STARTING_BLOCK))) ]]
<now> NOW </now>
<account>
<accountID> WHO </accountID>
<vestingBalance> VESTING_BALANCE </vestingBalance>
<startingBlock> STARTING_BLOCK </startingBlock>
<perBlock> PER_BLOCK </perBlock>
...
</account>
syntax Int ::= "vesting_balance" "(" AccountId ")" [function, functional]
// -------------------------------------------------------------------------
rule [[ vesting_balance(WHO) => minInt(FREE_BALANCE, locked_at(WHO)) ]]
<account>
<accountID> WHO </accountID>
<freeBalance> FREE_BALANCE </freeBalance>
...
</account>
Deposit into an existing account.
syntax EntryAction ::= "deposit_into_existing" "(" AccountId "," Int ")"
// ------------------------------------------------------------------------
rule [deposit-into-existing]:
<k> deposit_into_existing(WHO, AMOUNT) => . ... </k>
<totalIssuance> TOTAL_ISSUANCE => TOTAL_ISSUANCE +Int AMOUNT </totalIssuance>
<account>
<accountID> WHO </accountID>
<freeBalance> FREE_BALANCE => FREE_BALANCE +Int AMOUNT </freeBalance>
...
</account>
requires FREE_BALANCE >Int 0
End of module
endmodule