Vault Nomination¶
Overview¶
Vault Nomination is a feature aimed at increasing ONEBTC issuance capacity which introduces two actors: Nominators and Operators. Vaults who opt in to this feature take on the additional role of nomination Operators. A Nominator is anyone who locks their free collateral so that Operators they trust can issue ONEBTC backed by the nominated collateral. Nominators are rewarded a fraction of the fees generated by their collateral, while the rest of the fees is given to the Operator. Operators are assumed to be trusted by their nominators not to steal Bitcoin backed by nominated collateral.
Step-by-step¶
- Vaults opt in to the nomination feature, becoming Operators.
- The maximum nomination an Operator can receive is bounded by their own locked collateral.
- Nominators select one or more Operators and lock their collateral balance onto the BTC Bridge.
- Nominators can go offline and their nominated collateral will generate rewards passively.
- Operator and Nominator collateral cannot be withdrawn directly. Rather, withdrawals are subject to an unbonding period.
- In case of Operator failure, Nominators are returned any left-over collateral (after victim users are reimbursed).
Protocol¶
Security Assumptions and Considerations¶
- The operating Vault is trusted by its Nominators not to steal the ONEBTC issued with their collateral.
- There is no transitive trust. If a user trusts Vault A and Vault A trusts Vault B, the user does not trust Vault B.
- Nominators are mostly-offline agents, who are slow to respond to system changes.
- Vaults are always-online agents, who can promptly react to system updates.
- A Nominator may expose the Vault and the other Nominators to additional economic risk by withdrawing nominated collateral during an exchange rate spike. Similarly, the Vault may expose its Nominators to additional economic risk by withdrawing excess collateral.
- Note: in the usual case, this should be handled by having the different collateral thresholds (secure, premium redeem, liquidation). But in extreme cases (very high exchange rate volatility), it might cause concern.
Vault Nomination Protocol¶
- Vaults can choose to opt in and out of the Nomination protocol. If they opt-in they take on the additional role of an Operator.
- Nominators select an Operator to which they can delegate ONE balance as collateral. As a reward, they will earn a fraction of the ONEBTC and ONE fees generated by this collateral. The other fraction of these fees is received by the Operator.
- Vault replacement is disallowed for Operators with nominated collateral. Otherwise, Security Assumptions 1 and 2 would be violated.
- The nominated ONE:
- Is locked on the bridge
- Cannot be withdrawn by the operating Vault
- Is capped at a fraction of the Vault’s deposited collateral (Max Nomination Ratio). This prevents the Operator from withdrawing its entire collateral and only exposing Nominators to economic risk, or stealing without liquidation consequences. This means that an Operator can only withdraw collateral as long as the fraction of nominated collateral does not exceed the threshold cap. Capping Nominator collateral also prevents Operators being “outnumbered” by Nominators and their relative fee earnings being marginalized.
- Liquidation slashing is handled as follows.
- In case the collateral managed by the Operator falls below the liquidation threshold, the Operator and Nominators are slashed proportionally to their collateral.
- In case the Operator steals Bitcoin deposited at its address, its collateral is used to cover as much of the slashed amount as possible. If the Operator’s collateral was not enough to cover the entire amount, the Nominators are slashed proportionally for the remaining amount.
- Collateral withdrawals are first requested and then executed. A withdrawal request:
- Decreases the issuable ONEBTC capacity.
- May be cancelled if not executed. The amount in the cancelled withdrawal request becomes backing collateral again.
- Is subject to a window of delay (unbonding period) that allows Nominators and the Operator to react.
- Operator Unbonding Period. This window is longer, because Nominators are assumed to be mostly offline.
- Nominator Unbonding Period. This window is shorter, because the Vault Operator is assumed to always be online.
- Collateral withdrawals are subject to the following restrictions.
- The remaining collateralization of an operator must not be below the secure collateral threshold.
- Operator withdrawals must not cause nominated collateral to exceed the Max Nomination Ratio.
- Forced collateral withdrawal. If an operator’s withdrawal would result in a violation of the Max Nomination Ratio, automatically refund excess nominated collateral to the nominators, proportionally. Both the operator withdrawal and the nominator refunds are subject to the unbonding period.
- If an Operator issued zero ONEBTC, it can deregister and automatically refund Nominators their collateral.
- When an Operator is banned, its collateralization is lowered to the secure collateral threshold by automatically refunding nominated ONE, proportionally.
Data Model¶
Scalars¶
NominationEnabled¶
Flag indicating whether this feature is enabled.
As Operators may have issued ONEBTC
with nominated collateral when this feature is turned off,
a False
value of this scalar only prevents the opting in of new Operators.
MaxNominatorsPerOperator¶
Maximum number of nominators a single operator can have.
- Initial value: 100
OperatorUnbondingPeriod¶
Unbonding period, measured in blocks, that Operator withdrawal requests are subject to.
- Initial value: 14400 (24 hours)
NominatorUnbondingPeriod¶
Unbonding period, measured in blocks, that Nominator withdrawal requests are subject to.
- Initial value: 7200 (12 hours)
Structs¶
Nominator¶
Stores the information of a Nominator.
Parameter | Type | Description |
---|---|---|
id |
AccountId | The ID of the Nominator represented by this struct. |
collateral |
ONE | Collateral amount nominated. |
pendingWithdrawals |
BTreeMap | Mapping from the withdrawal request ID to the (maturityBlock, amount) tuple. |
collateralToBeWithdrawn |
ONE | Collateral that is not backing any ONEBTC and has been requested for withdrawal. |
Operator¶
Stores the information of an Operator.
Parameter | Type | Description |
---|---|---|
id |
AccountId | The ID of the Nominator represented by this struct. |
nominators |
BTreeMap | Mapping from the ID of a nominator to a Nominator struct. |
totalNominatedCollateral |
ONE | Total amount of collateral received as nomination. |
pendingWithdrawals |
BTreeMap | Mapping from the withdrawal request ID to the (maturityBlock, amount) tuple. |
collateralToBeWithdrawn |
ONE | Collateral that is not backing any ONEBTC and has been requested for withdrawal. |
Functions¶
getMaxNominationRatio¶
Returns the maximum nomination ratio (as %), denoting the maximum totalNominatedCollateral:operatorCollateral
value allowed.
- Example (current parameterization):
(1.5 / 1.2) - 1 = 25%
Function Sequence¶
- Return
(secureCollateralThreshold / auctionCollateralThreshold) - 1
setNominationEnabled¶
Set the feature flag for vault nomination.
Specification¶
Function Signature
setNominationEnabled(enabled)
Parameters
enabled
:True
if nomination should be enabled,False
if it should be disabled
Function Sequence¶
- Ensure the calling account is root.
- Set the NominationEnabled scalar to the value of the
enabled
parameter
optInToNomination¶
Become an Operator in the Vault Nomination protocol
Specification¶
Function Signature
optInToNomination(operatorId)
Parameters
operatorId
: the id of the vault to mark as Nomination Operator.
Events
NominationOptIn(operatorId)
Errors
VaultNominationDisabled
: the nomination feature is disabled.NotAVault
: the caller of the function is not a vault.VaultAlreadyOptedInToNomination
: the caller of the function is already opted in.
Function Sequence¶
- Check if the nomination feature is enabled. If not, throw
VaultNominationDisabled
. - Check if the caller is a vault. If not, throw
NotAVault
. - Check if the caller is not already opted in to nomination. If not, throw
VaultAlreadyOptedInToNomination
. - Instantiate an
Operator
struct. - Add the struct to the
Operators
mapping.
optOutOfNomination¶
Deregister from being an Operator in the Vault Nomination protocol.
Specification¶
Function Signature
optOutOfNomination(operatorId)
Parameters
operatorId
: the id of the vault to deregister from the nomination feature.
Events
NominationOptOut(operatorId)
Errors
VaultNotOptedInToNomination
: the caller is not an Operator.
Function Sequence¶
- Check if the caller is a nomination Operator. If not, throw
VaultNotOptedInToNomination
. - Immediately refund all nominated collateral, bypassing the unbonding period.
- Remove caller from the
Operators
mapping.
depositNominatedCollateral¶
Nominate collateral to a selected Operator.
Specification¶
Function Signature
depositNominatedCollateral(nominatorId, operatorId, amount)
Parameters
nominatorId
: the id of the user nominating collateral.operatorId
: the id of the operator to receive the nomination.amount
: the amount of collateral to nominate.
Events
IncreaseNominatedCollateral(nominatorId, operatorId, amount)
Errors
VaultNominationDisabled
: the nomination feature is disabled.VaultNotOptedInToNomination
: the vault is not an Operator.DepositViolatesMaxNominationRatio
: the amount of nomination would cause the Max Nomination Ratio to be exceeded for this operatorId.OperatorHasTooManyNominators
: the number of Nominators to the current Operator has reached MaxNominatorsPerOperator.
Function Sequence¶
- Check if the nomination feature is enabled. If not, throw
VaultNominationDisabled
. - Check if
operatorId
represents an operator. If not, throwVaultNotOptedInToNomination
. - Check that the additional nominated
amount
does not cause the Max Nomination Ratio to be exceeded. If not, throwDepositViolatesMaxNominationRatio
. - If the caller had no nomination to this Operator, check that the
MaxNominatorsPerOperator
would not be exceeded by receiving this nomination. IfMaxNominatorsPerOperator
would be exceeded, throwOperatorHasTooManyNominators
. - Update the
Operator
object to create or update theNominator
entry of the caller. - Move collateral from
nominatorId
to thebacking_collateral
ofoperatorId
in the Vault Registry.
requestOperatorCollateralWithdrawal¶
Request an operator collateral withdrawal, subject to an unbonding period.
Specification¶
Function Signature
requestOperatorCollateralWithdrawal(operatorId, amount)
Parameters
operatorId
: the id of the caller.amount
: the amount to withdraw.
Events
RequestOperatorCollateralWithdrawal(requestId, operatorId, maturity, amount)
Errors
VaultNotOptedInToNomination
: the caller is not an Operator.InsufficientCollateral
: the caller has requested to withdraw more collateral than it owns.
Function Sequence¶
- Check if
operatorId
is an operator. If not, throwVaultNotOptedInToNomination
. - Check if the operator has enough collateral of its own (excluding nominations). If not, throw
InsufficientCollateral
. - Immediately refund, proportionally, nominated collateral that would cause the Max Nomination Ratio to be exceeded.
- Add the withdrawal request to the
pendingWithdrawals
array in theOperator
struct. - Decrease the
backing_collateral
ofoperatorId
in the Vault Registry.
requestNominatorCollateralWithdrawal¶
Request a nominator collateral withdrawal, subject to an unbonding period.
Specification¶
Function Signature
requestNominatorCollateralWithdrawal(nominatorId, operatorId, amount)
Parameters
nominatorId
: the id of the requester.operatorId
: the id of the operator to withdraw from.amount
: the amount to withdraw.
Events
RequestNominatorCollateralWithdrawal(requestId, nominatorId, operatorId, maturity, amount)
Errors
VaultNotOptedInToNomination
: theoperatorId
is not an Operator.NominatorNotFound
: thenominatorId
is not a Nominator.TooLittleNominatedCollateral
: the caller has requested to withdraw more collateral than it owns.
Function Sequence¶
- Check
operatorId
is an operator. If not, throwVaultNotOptedInToNomination
. - Check
nominatorId
is a nominator. If not, throwNominatorNotFound
. - Check if the caller has at least as much nominated collateral as
amount
. If not, throwTooLittleNominatedCollateral
. - Add the withdrawal request to the
pendingWithdrawals
array in theNominator
struct fornominatorId
, inside theOperator
struct ofoperatorId
. - Decrease the
backing_collateral
ofoperatorId
in the Vault Registry.
executeOperatorWithdrawal¶
Execute all matured (unbonded) withdrawal requests of an operator.
Specification¶
Function Signature
executeOperatorWithdrawal(operatorId)
Parameters
operatorId
: the id of the requester.
Events
ExecuteOperatorCollateralWithdrawal(operatorId, unbondedCollateral)
Errors
VaultNotOptedInToNomination
: theoperatorId
is not an Operator.NoMaturedCollateral
: either no collateral withdrawal has been requested, or the requests have not matured yet.
Function Sequence¶
- Check
operatorId
is an operator. If not, throwVaultNotOptedInToNomination
. - Iterate through the
withdrawalRequests
in theOperator
struct to determine how much collateral was unbonded, removing matured requests. - If there is zero unbonded collateral, throw
NoMaturedCollateral
.
executeNominatorWithdrawal¶
Execute all matured (unbonded) withdrawal requests of a nominator.
Specification¶
Function Signature
executeNominatorWithdrawal(nominatorId, operatorId)
Parameters
nominatorId
: the id of the requester.operatorId
: the id of the operator.
Events
ExecuteNominatorCollateralWithdrawal(nominatorId, operatorId, unbondedCollateral)
Errors
VaultNotOptedInToNomination
: theoperatorId
is not an Operator.NoMaturedCollateral
: either no collateral withdrawal has been requested, or the requests have not matured yet.NominatorNotFound
: thenominatorId
is not a Nominator.
Function Sequence¶
- Check
operatorId
is an operator. If not, throwVaultNotOptedInToNomination
. - Check
nominatorId
is a nominator. If not, throwNominatorNotFound
. - Iterate through the
withdrawalRequests
array in theNominator
struct inside theOperator
struct foroperatorId
. Determine how much collateral was unbonded, removing matured requests. - If there is zero unbonded collateral, throw
NoMaturedCollateral
.
cancelOperatorWithdrawal¶
Cancel an operator’s withdrawal request.
Specification¶
Function Signature
cancelOperatorWithdrawal(operatorId, requestId)
Parameters
operatorId
: the id of the operator.requestId
: the id of the withdrawal request.
Events
CancelOperatorCollateralWithdrawal(requestId, operatorId)
Errors
VaultNotOptedInToNomination
: theoperatorId
is not an Operator.WithdrawalRequestNotFound
: no withdrawal request found for the given id.
Function Sequence¶
- Check
operatorId
is an operator. If not, throwVaultNotOptedInToNomination
. - Check
requestId
corresponds to an actual withdrawal request. If not, throwWithdrawalRequestNotFound
. - Remove the withdrawal request from the
withdrawalRequests
array in theOperator
struct foroperatorId
. - Increase the backing collateral of
operatorId
in the Vault Registry by the amount in the withdrawal request.
cancelNominatorWithdrawal¶
Cancel a nominator’s withdrawal request.
Specification¶
Function Signature
cancelNominatorWithdrawal(nominatorId, operatorId, requestId)
Parameters
nominatorId
: the id of the nominator.operatorId
: the id of the operator.requestId
: the id of the withdrawal request.
Events
CancelNominatorCollateralWithdrawal(requestId, nominatorId, operatorId)
Errors
VaultNotOptedInToNomination
: theoperatorId
is not an Operator.NominatorNotFound
: thenominatorId
is not a Nominator.WithdrawalRequestNotFound
: no withdrawal request found for the given id.
Function Sequence¶
- Check
operatorId
is an operator. If not, throwVaultNotOptedInToNomination
. - Check
nominatorId
is a nominator. If not, throwNominatorNotFound
. - Check
requestId
corresponds to an actual withdrawal request. If not, throwWithdrawalRequestNotFound
.
- Remove the withdrawal request from the
withdrawalRequests
array in theNominator
struct inside theOperator
struct foroperatorId
. - Increase the backing collateral of
operatorId
in the Vault Registry by the amount in the withdrawal request.
Events¶
NominationOptIn¶
Event Signature
NominationOptIn(account)
Parameters
account
: the id of the operator who opten in
Functions
NominationOptOut¶
Event Signature
NominationOptOut(account)
Parameters
account
: the id of the operator who opten out
Functions
IncreaseNominatedCollateral¶
Event Signature
IncreaseNominatedCollateral(nominatorId, operatorId, amount)
Parameters
nominatorId
: the id of the nominator who is depositing collateraloperatorId
: the id of the operator who receives the nominationamount
: the amount of nominated collateral
Functions
RequestOperatorCollateralWithdrawal¶
Event Signature
RequestOperatorCollateralWithdrawal(requestId, operatorId, maturityBlock, amount)
Parameters
requestId
: the id of the requestoperatorId
: the id of the operator withdrawing collateralmaturityBlock
: the block when the request can be executedamount
: the amount to withdraw
Functions
ExecuteOperatorCollateralWithdrawal¶
Event Signature
ExecuteOperatorCollateralWithdrawal(operatorId, amount)
Parameters
operatorId
: the id of the operator withdrawing collateralamount
: the withdrawn amount
Functions
CancelOperatorCollateralWithdrawal¶
Event Signature
CancelOperatorCollateralWithdrawal(requestId, operatorId)
Parameters
requestId
: the id of the withdrawal request to canceloperatorId
: the id of the operator who requested the withdrawal
Functions
RequestNominatorCollateralWithdrawal¶
Event Signature
RequestNominatorCollateralWithdrawal(requestId, nominatorId, operatorId, maturityBlock, amount)
Parameters
requestId
: the id of the requestnominatorId
: the id of the operator withdrawing collateraloperatorId
: the id of the operator who nominated collateral is being withdrawnmaturityBlock
: the block when the request can be executedamount
: the amount to withdraw
Functions
ExecuteNominatorCollateralWithdrawal¶
Event Signature
ExecuteNominatorCollateralWithdrawal(nominatorId, operatorId, amount)
Parameters
nominatorId
: the id of the operator withdrawing collateraloperatorId
: the id of the operator who nominated collateral is being withdrawnamount
: the withdrawn amount
Functions
CancelNominatorCollateralWithdrawal¶
Event Signature
CancelNominatorCollateralWithdrawal(requestId, nominatorId, operatorId)
Parameters
requestId
: the id of the withdrawal request to cancelnominatorId
: the id of the nominator who requested the withdrawaloperatorId
: the id of the operator who nominated collateral is being withdrawn
Functions