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
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 theOP_RETURN
of 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.
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 toERROR:1
withErrors
containing onlyLIQUIDATION
. All other states are disallowed.
Function Sequence¶
- Check if the
amountONEBTC
is less or equal to the user’s balance in the treasury. ReturnERR_AMOUNT_EXCEEDS_USER_BALANCE
if this check fails. - Retrieve the
vault
from Vault Registry. ReturnERR_VAULT_NOT_FOUND
if no vault can be found. - Check that the
vault
is currently not banned, i.e.,vault.bannedUntil == None
orvault.bannedUntil < current shard block height
. ReturnERR_VAULT_BANNED
if this check fails. - Check if the
amountONEBTC
is less or equal to theissuedTokens
by the selected vault in the VaultRegistry. ReturnERR_AMOUNT_EXCEEDS_VAULT_BALANCE
if this check fails. - Check that the
amountONEBTC
is above the Bitcoin dust limit. - Call the Vault Registry increaseToBeRedeemedTokens function with the
amountBTC
of tokens to be redeemed and thevault
identified by its address. - Call the lock function in the Treasury to lock the ONEBTC
amount
of the user. - Generate a
redeemId
using generateSecureId, passingredeemer
as 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
Redeem
struct in theRedeemRequests
mapping asRedeemRequests[redeemId] = redeem
, where:redeem.vault
is the requestedvault
redeem.opentime
is the current block numberredeem.amountONEBTC
is theamount
provided as inputredeem.amountBTC = amountBTC
redeem.amountONE = amountONE
redeem.premiumONE = premiumONE
redeem.redeemer
is the redeemer accountredeem.btcAddress
the Bitcoin address of the user.
- Emit the
RequestRedeem
event with theredeemId
,redeemer
account,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:0
or toERROR:1
withErrors
containing onlyLIQUIDATION
. All other states are disallowed. - The selected vault must not have been banned.
Function Sequence¶
- Check if the
amountONEBTC
is less or equal to the user’s balance in the treasury. ReturnERR_AMOUNT_EXCEEDS_USER_BALANCE
if this check fails. - Check if the
amountONEBTC
is less or equal to theissuedTokens
by the LiquidationVault in the VaultRegistry. ReturnERR_AMOUNT_EXCEEDS_VAULT_BALANCE
if this check fails. - Call the Vault Registry redeemTokensLiquidation function with the
amountBTC
of tokens to be redeemed. - Call the lock and burn functions in the Treasury to lock the ONEBTC
amount
of the user. - Emit the
LiquidationRedeem
event with theredeemer
account 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 therequestRedeem
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
: TheredeemId
cannot be found.ERR_REDEEM_PERIOD_EXPIRED
: The time limit as defined by theRedeemPeriod
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.
Function Sequence¶
Check if the
vault
is theredeem.vault
. ReturnERR_UNAUTHORIZED
if called by any account other than the associatedredeem.vault
.Check if the
redeemId
exists. ReturnERR_REDEEM_ID_NOT_FOUND
if 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
, andmerkleProof
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
), theredeemer
’s Bitcoin address (redeem.btcAddress
), and theredeemId
as 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.amount
of ONEBTC of the user.Check
redeem.premiumONE > 0
:- If
True
, call redeemTokensPremium in the VaultRegistry to release the Vault’s collateral with theredeem.vault
and theredeem.amount
, andredeemer
andpremiumONE
to 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.vault
and theredeem.amount
.
- If
Remove
redeem
fromRedeemRequests
.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 theredeemId
that is cancelled.
Errors
ERR_REDEEM_ID_NOT_FOUND
: TheredeemId
cannot be found.ERR_REDEEM_PERIOD_NOT_EXPIRED
: Raises an error if the time limit to callexecuteRedeem
has not yet passed.
Preconditions¶
- None.
Function Sequence¶
- Check if an redeem with id
redeemId
exists. 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.amount
parameters. - Call the burn function in the Treasury to burn the
redeem.amount
of ONEBTC of the user. - Call slashCollateral in the Collateral module, passing
redeem.vault
,redeem.redeemer
and 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.redeemer
and 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
redeem
fromRedeemRequests
. - Emit a
CancelRedeem
event with theredeemer
account 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 therequestRedeem
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 theRedeemRequests
mapping returnedNone
.
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.