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¶
- Precondition: A user owns ONEBTC.
- 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.
- The selected vault listens for the
RequestRedeemevent 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 theOP_RETURNof one output. - 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.
- 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.
- Optional: If one or more vaults are liquidated, a user can execute a liquidationRedeem.
Vault Registry¶
The data access and state changes to the vault registry are documented in Fig. 8 below.
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:0or toERROR:1withErrorscontaining onlyLIQUIDATION. All other states are disallowed.
Function Sequence¶
- Check if the
amountONEBTCis less or equal to the user’s balance in the treasury. ReturnERR_AMOUNT_EXCEEDS_USER_BALANCEif this check fails. - Retrieve the
vaultfrom Vault Registry. ReturnERR_VAULT_NOT_FOUNDif no vault can be found. - Check that the
vaultis currently not banned, i.e.,vault.bannedUntil == Noneorvault.bannedUntil < current shard block height. ReturnERR_VAULT_BANNEDif this check fails. - Check if the
amountONEBTCis less or equal to theissuedTokensby the selected vault in the VaultRegistry. ReturnERR_AMOUNT_EXCEEDS_VAULT_BALANCEif this check fails. - Check that the
amountONEBTCis above the Bitcoin dust limit. - Call the Vault Registry increaseToBeRedeemedTokens function with the
amountBTCof tokens to be redeemed and thevaultidentified by its address. - Call the lock function in the Treasury to lock the ONEBTC
amountof the user. - Generate a
redeemIdusing generateSecureId, passingredeemeras parameter. - Check if the Vault’s collateral rate is below
PremiumRedeemThreshold. If this is the case, setpremiumONE = RedeemPremiumFee(as per Vault Registry). Otherwise setpremiumONE = 0. - Store a new
Redeemstruct in theRedeemRequestsmapping asRedeemRequests[redeemId] = redeem, where:redeem.vaultis the requestedvaultredeem.opentimeis the current block numberredeem.amountONEBTCis theamountprovided as inputredeem.amountBTC = amountBTCredeem.amountONE = amountONEredeem.premiumONE = premiumONEredeem.redeemeris the redeemer accountredeem.btcAddressthe Bitcoin address of the user.
- Emit the
RequestRedeemevent with theredeemId,redeemeraccount,amount,vault, andbtcAddress.
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:0or toERROR:1withErrorscontaining onlyLIQUIDATION. All other states are disallowed. - The selected vault must not have been banned.
Function Sequence¶
- Check if the
amountONEBTCis less or equal to the user’s balance in the treasury. ReturnERR_AMOUNT_EXCEEDS_USER_BALANCEif this check fails. - Check if the
amountONEBTCis less or equal to theissuedTokensby the LiquidationVault in the VaultRegistry. ReturnERR_AMOUNT_EXCEEDS_VAULT_BALANCEif this check fails. - Call the Vault Registry redeemTokensLiquidation function with the
amountBTCof tokens to be redeemed. - Call the lock and burn functions in the Treasury to lock the ONEBTC
amountof the user. - Emit the
LiquidationRedeemevent with theredeemeraccount andamountBTC.
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 therequestRedeemfunction.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: TheredeemIdcannot be found.ERR_REDEEM_PERIOD_EXPIRED: The time limit as defined by theRedeemPeriodis 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.
Function Sequence¶
Check if the
vaultis theredeem.vault. ReturnERR_UNAUTHORIZEDif called by any account other than the associatedredeem.vault.Check if the
redeemIdexists. ReturnERR_REDEEM_ID_NOT_FOUNDif not found.Check if the redeem has expired by calling hasExpired in the Security module. If true, throws
ERR_REDEEM_PERIOD_EXPIRED.Verify the transaction.
- Call verifyTransactionInclusion in BTC-Relay, providing
txId,txBlockHeight,txIndex, andmerkleProofas 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), theredeemer’s Bitcoin address (redeem.btcAddress), and theredeemIdas parameters. If this call returns an error, abort and return the received error.
- Call verifyTransactionInclusion in BTC-Relay, providing
Call the burn function in the Treasury to burn the
redeem.amountof ONEBTC of the user.Check
redeem.premiumONE > 0:- If
True, call redeemTokensPremium in the VaultRegistry to release the Vault’s collateral with theredeem.vaultand theredeem.amount, andredeemerandpremiumONEto allocate the ONE premium to the redeemer using the Vault’s released collateral. - Else call redeemTokens function in the VaultRegistry to release the Vault’s collateral with the
redeem.vaultand theredeem.amount.
- If
Remove
redeemfromRedeemRequests.Emit an
ExecuteRedeemevent 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 theredeemIdthat is cancelled.
Errors
ERR_REDEEM_ID_NOT_FOUND: TheredeemIdcannot be found.ERR_REDEEM_PERIOD_NOT_EXPIRED: Raises an error if the time limit to callexecuteRedeemhas not yet passed.
Preconditions¶
- None.
Function Sequence¶
- Check if an redeem with id
redeemIdexists. If not, throwERR_REDEEM_ID_NOT_FOUND. Otherwise, load the redeem requestredeem = RedeemRequests[redeemId]. - Check if the redeem has expired by calling hasExpired in the Security module. If false, throw
ERR_REDEEM_PERIOD_NOT_EXPIRED. - Retrieve the current BTC-ONE exchange rate (
exchangeRate) via getExchangeRate from the Exchange Rate Oracle. - If
reimburse == True(user requested to be reimbursed in ONE):- 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, andredeem.amountparameters. - Call the burn function in the Treasury to burn the
redeem.amountof ONEBTC of the user. - Call slashCollateral in the Collateral module, passing
redeem.vault,redeem.redeemerand the value of the reimbursed collateral, calculated asredeem.amountONEBTC *getExchangeRate* (1 + PunishmentFee / 100000)
- Call the decreaseTokens function in the VaultRegistry to transfer (a part) of the Vault’s collateral to the user with the
- Else, if
reimburse == False(user does not want full reimbursement and wishes to retry the redeem)
- Call slashCollateral in the Collateral module, passing
redeem.vault,redeem.redeemerand value of the collateral punishment, calculated asredeem.amountONEBTC *getExchangeRate* (PunishmentFee / 100000)
- Temporarily Ban the vault from issue, redeem and replace processes by setting
redeem.vault.bannedUntil = current shard block height + PunishmentDelay. - Remove
redeemfromRedeemRequests. - Emit a
CancelRedeemevent with theredeemeraccount identifier and theredeemId.
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 therequestRedeemfunction,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
redeemIdcannot be found.” - Function: executeRedeem
- Cause: The
redeemIdin theRedeemRequestsmapping returnedNone.
ERR_REDEEM_PERIOD_EXPIRED
- Message: “The redeem period expired.”
- Function: executeRedeem
- Cause: The time limit as defined by the
RedeemPeriodis 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
executeRedeemhas not yet passed.