Redeem

Overview

The redeem module allows a user to receive BTC on the Bitcoin chain in return for destroying an equivalent amount of ONEBTC on the BTC Bridge. The process is initiated by a user requesting a redeem with a vault. The vault then needs to send BTC to the user within a given time limit. Next, the vault has to finalize the process by providing a proof to the BTC Bridge that he has send the right amount of BTC to the user. If the vault fails to deliver a valid proof within the time limit, the user can claim an equivalent amount of ONE from the vault’s locked collateral to reimburse him for his loss in BTC.

Moreover, as part of the liquidation procedure, users are able to directly exchange ONEBTC for ONE. To this end, a user is able to execute a special liquidation redeem if one or multiple vaults have been liquidated.

Step-by-step

  1. Precondition: A user owns ONEBTC.
  2. A user locks an amount of ONEBTC by calling the requestRedeem function. In this function call, the user selects a vault to execute the redeem request from the list of vaults. The function creates a redeem request with a unique hash.
  3. The selected vault listens for the RequestRedeem event emitted by the user. The vault then proceeds to transfer BTC to the address specified by the user in the requestRedeem function including a unique hash in the OP_RETURN of one output.
  4. The vault executes the executeRedeem function by providing the Bitcoin transaction from step 3 together with the redeem request identifier within the time limit. If the function completes successfully, the locked ONEBTC are destroyed and the user received its BTC.
  5. Optional: If the user could not receive BTC within the given time (as required in step 4), the user calls cancelRedeem after the redeem time limit. The user is then refunded with the ONE collateral the vault provided.
  6. Optional: If one or more vaults are liquidated, a user can execute a liquidationRedeem.

Security

  • Unique identification of Bitcoin payments: OP_RETURN

Vault Registry

The data access and state changes to the vault registry are documented in Fig. 8 below.

vault-registry-redeem

Fig. 8 The redeem module interacts through three different functions with the vault registry.

Fee Model

Following additions are added if the fee model is integrated.

  • Redeem fees are paid by users in ONEBTC when executing the request. The fees are transferred to Bridge Fee Pool.
  • If a redeem request is canceled, the user has two choices:
    • If the user selects to reimburse, the ONE equivalent of ONEBTC at the current exchange rate plus the punishment fee is deducted from the vault and transferred to the user.
    • If the user does not reimburse, the punishment fee is deducted from the vaults collateral and transferred to the user.
    • NOTE: with the SLA model additions, the punishment fee paid to the user stays constant (i.e., the user always receives the punishment fee of e.g. 10%). However, vaults may be slashed more than the punishment fee, as determined by the SLA. The surplus slashed collateral is routed into the Bridge Fee pool and handled like regular fee income. For example, if the vault is punished with 20%, 10% punishment fee is paid to the user and 10% is paid to the fee pool.

Data Model

Scalars

RedeemPeriod

The time difference between when a redeem request is created and required completion time by a vault. Concretely, this period is the amount by which ActiveBlockCount is allowed to increase before the redeem is considered to be expired. The period has an upper limit to ensure the user gets his BTC in time and to potentially punish a vault for inactivity or stealing BTC.

Maps

RedeemRequests

Users create redeem requests to receive BTC in return for ONEBTC. This mapping provides access from a unique hash redeemId to a Redeem struct. <redeemId, Redeem>.

Structs

Redeem

Stores the status and information about a single redeem request.

Parameter Type Description
vault Account The BTC Bridge address of the vault responsible for this redeem request.
opentime u256 Block height of opening the request.
amountONEBTC ONEBTC Amount of ONEBTC the user requested to be redeemed.
amountBTC BTC Amount of BTC to be released to the user.
amountONE ONE Amount of ONE to be paid to the user from liquidated Vaults’ collateral (when LIQUIDATION error indicated in Security).
premiumONE ONE Amount of ONE to be paid as a premium to this user (if the Vault’s collateral rate was below PremiumRedeemThreshold at the time of redeeming).
redeemer Account The BTC Bridge address of the user requesting the redeem.
btcAddress bytes[20] Base58 encoded Bitcoin public key of the User.

Functions

requestRedeem

A user requests to start the redeem procedure. This function checks the BTC Bridge status in Security and decides how the redeem process is to be executed. The following modes are possible:

  • Normal Redeem - no errors detected, full BTC value is to be Redeemed.
  • Premium Redeem - the selected Vault’s collateral rate has fallen below PremiumRedeemThreshold. Full BTC value is to be redeemed, but the user is allocated a premium in ONE (RedeemPremiumFee), taken from the Vault’s to-be-released collateral.

Specification

Function Signature

requestRedeem(redeemer, amountONEBTC, btcPublicKey, vault)

Parameters

  • redeemer: address of the user triggering the redeem.
  • amountONEBTC: the amount of ONEBTC to destroy and BTC to receive.
  • btcAddress: the address to receive BTC.
  • vault: the vault selected for the redeem request.

Returns

  • redeemId: A unique hash identifying the redeem request.

Events

  • RequestRedeem(redeemId, redeemer, amount, vault, btcAddress)

Errors

  • ERR_VAULT_NOT_FOUND = "There exists no vault with the given account id": The specified vault does not exist.
  • ERR_AMOUNT_EXCEEDS_USER_BALANCE: If the user is trying to redeem more BTC than his ONEBTC balance.
  • ERR_AMOUNT_EXCEEDS_VAULT_BALANCE: If the user is trying to redeem from a vault that has less BTC locked than requested for redeem.
  • ERR_VAULT_BANNED = "The selected vault has been temporarily banned.": Redeem requests are not possible with temporarily banned Vaults.

Preconditions

  • The BTC Bridge status in the Security component must be set to RUNNING:0 or to ERROR:1 with Errors containing only LIQUIDATION. All other states are disallowed.

Function Sequence

  1. Check if the amountONEBTC is less or equal to the user’s balance in the treasury. Return ERR_AMOUNT_EXCEEDS_USER_BALANCE if this check fails.
  2. Retrieve the vault from Vault Registry. Return ERR_VAULT_NOT_FOUND if no vault can be found.
  3. Check that the vault is currently not banned, i.e., vault.bannedUntil == None or vault.bannedUntil < current shard block height. Return ERR_VAULT_BANNED if this check fails.
  4. Check if the amountONEBTC is less or equal to the issuedTokens by the selected vault in the VaultRegistry. Return ERR_AMOUNT_EXCEEDS_VAULT_BALANCE if this check fails.
  5. Check that the amountONEBTC is above the Bitcoin dust limit.
  6. Call the Vault Registry increaseToBeRedeemedTokens function with the amountBTC of tokens to be redeemed and the vault identified by its address.
  7. Call the lock function in the Treasury to lock the ONEBTC amount of the user.
  8. Generate a redeemId using generateSecureId, passing redeemer as parameter.
  9. Check if the Vault’s collateral rate is below PremiumRedeemThreshold. If this is the case, set premiumONE = RedeemPremiumFee (as per Vault Registry). Otherwise set premiumONE = 0.
  10. Store a new Redeem struct in the RedeemRequests mapping as RedeemRequests[redeemId] = redeem, where:
    • redeem.vault is the requested vault
    • redeem.opentime is the current block number
    • redeem.amountONEBTC is the amount provided as input
    • redeem.amountBTC = amountBTC
    • redeem.amountONE = amountONE
    • redeem.premiumONE = premiumONE
    • redeem.redeemer is the redeemer account
    • redeem.btcAddress the Bitcoin address of the user.
  11. Emit the RequestRedeem event with the redeemId, redeemer account, amount, vault, and btcAddress.

liquidationRedeem

A user executes a liquidation redeem that exchanges ONEBTC for ONE from the LiquidationVault. The BTC Bridge is in ERROR state with LIQUIDATION error code. The 1:1 backing is being recovered, hence this function burns ONEBTC without releasing any BTC. The user is also allocated the PunishmentFee in ONE as reimbursement for possible opportunity costs.

Specification

Function Signature

liquidationRedeem(redeemer, amountONEBTC)

Parameters

  • redeemer: address of the user triggering the redeem.
  • amountONEBTC: the amount of ONEBTC to destroy.

Returns

  • redeemId: A unique hash identifying the redeem request.

Events

  • RequestRedeem(redeemId, redeemer, amount, vault, btcAddress)

Errors

  • ERR_VAULT_NOT_FOUND = "There exists no vault with the given account id": The specified vault does not exist.
  • ERR_AMOUNT_EXCEEDS_USER_BALANCE: If the user is trying to redeem more BTC than his ONEBTC balance.
  • ERR_AMOUNT_EXCEEDS_VAULT_BALANCE: If the user is trying to redeem from a vault that has less BTC locked than requested for redeem.
  • ERR_VAULT_BANNED = "The selected vault has been temporarily banned.": Redeem requests are not possible with temporarily banned Vaults.

Preconditions

  • The BTC Bridge status in the Security component must be set to RUNNING:0 or to ERROR:1 with Errors containing only LIQUIDATION. All other states are disallowed.
  • The selected vault must not have been banned.

Function Sequence

  1. Check if the amountONEBTC is less or equal to the user’s balance in the treasury. Return ERR_AMOUNT_EXCEEDS_USER_BALANCE if this check fails.
  2. Check if the amountONEBTC is less or equal to the issuedTokens by the LiquidationVault in the VaultRegistry. Return ERR_AMOUNT_EXCEEDS_VAULT_BALANCE if this check fails.
  3. Call the Vault Registry redeemTokensLiquidation function with the amountBTC of tokens to be redeemed.
  4. Call the lock and burn functions in the Treasury to lock the ONEBTC amount of the user.
  5. Emit the LiquidationRedeem event with the redeemer account and amountBTC.

executeRedeem

A vault calls this function after receiving an RequestRedeem event with his public key. Before calling the function, the vault transfers the specific amount of BTC to the BTC address given in the original redeem request. The vault completes the redeem with this function.

Specification

Function Signature

executeRedeem(vault, redeemId, merkleProof, rawTx)

Parameters

  • vault: the vault responsible for executing this redeem request.
  • redeemId: the unique hash created during the requestRedeem function.
  • merkleProof: Merkle tree path (concatenated LE SHA256 hashes).
  • rawTx: Raw Bitcoin transaction including the transaction inputs and outputs.

Events

  • ExecuteRedeem(redeemer, redeemId, amount, vault):

Errors

  • ERR_REDEEM_ID_NOT_FOUND: The redeemId cannot be found.
  • ERR_REDEEM_PERIOD_EXPIRED: The time limit as defined by the RedeemPeriod is not met.
  • ERR_UNAUTHORIZED = Unauthorized: Caller must be associated vault: The caller of this function is not the associated vault, and hence not authorized to take this action.

Preconditions

  • The BTC Bridge status in the Security component must be set to RUNNING:0.

Function Sequence

  1. Check if the vault is the redeem.vault. Return ERR_UNAUTHORIZED if called by any account other than the associated redeem.vault.

  2. Check if the redeemId exists. Return ERR_REDEEM_ID_NOT_FOUND if not found.

  3. Check if the redeem has expired by calling hasExpired in the Security module. If true, throws ERR_REDEEM_PERIOD_EXPIRED.

  4. Verify the transaction.

    • Call verifyTransactionInclusion in BTC-Relay, providing txId, txBlockHeight, txIndex, and merkleProof as parameters. If this call returns an error, abort and return the received error.
    • Call validateTransaction in BTC-Relay, providing rawTx, the amount of to-be-redeemed BTC (redeem.amount), the redeemer’s Bitcoin address (redeem.btcAddress), and the redeemId as parameters. If this call returns an error, abort and return the received error.
  5. Call the burn function in the Treasury to burn the redeem.amount of ONEBTC of the user.

  6. Check redeem.premiumONE > 0:

    1. If True, call redeemTokensPremium in the VaultRegistry to release the Vault’s collateral with the redeem.vault and the redeem.amount, and redeemer and premiumONE to allocate the ONE premium to the redeemer using the Vault’s released collateral.
    2. Else call redeemTokens function in the VaultRegistry to release the Vault’s collateral with the redeem.vault and the redeem.amount.
  7. Remove redeem from RedeemRequests.

  8. Emit an ExecuteRedeem event with the user’s address, the redeemId, the amount, and the Vault’s address.

cancelRedeem

If a redeem request is not completed on time, the redeem request can be cancelled. The user that initially requested the redeem process calls this function to obtain the Vault’s collateral as compensation for not refunding the BTC back to his address.

The failed vault is banned from further issue, redeem and replace requests for a pre-defined time period (PunishmentDelay as defined in Vault Registry).

Specification

Function Signature

cancelRedeem(redeemId, reimburse)

Parameters

  • redeemId: the unique hash of the redeem request.
  • reimburse: boolean flag, specifying if the user wishes to be reimbursed in ONE and slash the vault, or wishes to keep the ONEBTC (and retry to redeem with another Vault).

Events

  • CancelRedeem(redeemer, redeemId): Emits an event with the redeemId that is cancelled.

Errors

  • ERR_REDEEM_ID_NOT_FOUND: The redeemId cannot be found.
  • ERR_REDEEM_PERIOD_NOT_EXPIRED: Raises an error if the time limit to call executeRedeem has not yet passed.

Preconditions

  • None.

Function Sequence

  1. Check if an redeem with id redeemId exists. If not, throw ERR_REDEEM_ID_NOT_FOUND. Otherwise, load the redeem request redeem = RedeemRequests[redeemId].
  2. Check if the redeem has expired by calling hasExpired in the Security module. If false, throw ERR_REDEEM_PERIOD_NOT_EXPIRED.
  3. Retrieve the current BTC-ONE exchange rate (exchangeRate) via getExchangeRate from the Exchange Rate Oracle.
  4. If reimburse == True (user requested to be reimbursed in ONE):
    1. Call the decreaseTokens function in the VaultRegistry to transfer (a part) of the Vault’s collateral to the user with the redeem.vault, redeem.redeemer, and redeem.amount parameters.
    2. Call the burn function in the Treasury to burn the redeem.amount of ONEBTC of the user.
    3. Call slashCollateral in the Collateral module, passing redeem.vault, redeem.redeemer and the value of the reimbursed collateral, calculated as redeem.amountONEBTC * getExchangeRate * (1 + PunishmentFee / 100000)
  1. Else, if reimburse == False (user does not want full reimbursement and wishes to retry the redeem)
  1. Call slashCollateral in the Collateral module, passing redeem.vault, redeem.redeemer and value of the collateral punishment, calculated as redeem.amountONEBTC * getExchangeRate * (PunishmentFee / 100000)
  1. Temporarily Ban the vault from issue, redeem and replace processes by setting redeem.vault.bannedUntil = current shard block height + PunishmentDelay.
  2. Remove redeem from RedeemRequests.
  3. Emit a CancelRedeem event with the redeemer account identifier and the redeemId.

Events

RequestRedeem

Emit an event when a redeem request is created. This event needs to be monitored by the vault to start the redeem request.

Event Signature

RequestRedeem(redeemId, redeemer, amountONEBTC, vault, btcAddress)

Parameters

  • redeemId: The unique identifier of this redeem request.
  • redeemer: address of the user triggering the redeem.
  • amountONEBTC: the amount of ONEBTC to destroy and BTC to receive.
  • btcAddress: the address to receive BTC.
  • vault: the vault selected for the redeem request.

Functions

  • ref:requestRedeem

LiquidationRedeem

Emit an event when a user creates a liquidation redeem.

Event Signature

LiquidationRedeem(redeemer, amountONEBTC)

Parameters

  • redeemer: address of the user triggering the redeem.
  • amountONEBTC: the amount of ONEBTC to destroy and BTC to receive.

Functions

  • ref:liquidationRedeem

ExecuteRedeem

Emit an event when a redeem request is successfully executed by a vault.

Event Signature

ExecuteRedeem(redeemer, redeemId, amountONEBTC, vault)

Parameters

  • redeemer: address of the user triggering the redeem.
  • redeemId: the unique hash created during the requestRedeem function,
  • amountONEBTC: the amount of ONEBTC to destroy and BTC to receive.
  • vault: the vault responsible for executing this redeem request.

Functions

  • ref:executeRedeem

CancelRedeem

Emit an event when a user cancels a redeem request that has not been fulfilled after the RedeemPeriod has passed.

Event Signature

CancelRedeem(redeemer, redeemId)

Parameters

  • redeemer: The redeemer starting the redeem process.
  • redeemId: the unique hash of the redeem request.

Functions

  • ref:cancelRedeem

Error Codes

ERR_VAULT_NOT_FOUND

  • Message: “There exists no vault with the given account id.”
  • Function: requestRedeem, liquidationRedeem
  • Cause: The specified vault does not exist.

ERR_AMOUNT_EXCEEDS_USER_BALANCE

  • Message: “The requested amount exceeds the user’s balance.”
  • Function: requestRedeem, liquidationRedeem
  • Cause: If the user is trying to redeem more BTC than his ONEBTC balance.

ERR_VAULT_BANNED

  • Message: “The selected vault has been temporarily banned.”
  • Function: requestRedeem
  • Cause: Redeem requests are not possible with temporarily banned Vaults

ERR_AMOUNT_EXCEEDS_VAULT_BALANCE

  • Message: “The requested amount exceeds the vault’s balance.”
  • Function: requestRedeem, liquidationRedeem
  • Cause: If the user is trying to redeem from a vault that has less BTC locked than requested for redeem.

ERR_REDEEM_ID_NOT_FOUND

  • Message: “The redeemId cannot be found.”
  • Function: executeRedeem
  • Cause: The redeemId in the RedeemRequests mapping returned None.

ERR_REDEEM_PERIOD_EXPIRED

  • Message: “The redeem period expired.”
  • Function: executeRedeem
  • Cause: The time limit as defined by the RedeemPeriod is not met.

ERR_UNAUTHORIZED

  • Message: “Unauthorized: Caller must be associated vault.”
  • Function: executeRedeem
  • Cause: The caller of this function is not the associated vault, and hence not authorized to take this action.

ERR_REDEEM_PERIOD_NOT_EXPIRED

  • Message: “The period to complete the redeem request is not yet expired.”
  • Function: cancelRedeem
  • Cause: Raises an error if the time limit to call executeRedeem has not yet passed.