Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redemptions veto mechanism #788

Merged
merged 24 commits into from
Mar 6, 2024
Merged

Redemptions veto mechanism #788

merged 24 commits into from
Mar 6, 2024

Conversation

lukasz-zimnoch
Copy link
Member

@lukasz-zimnoch lukasz-zimnoch commented Feb 20, 2024

Closes: #781

Here we present the implementation of the redemptions veto mechanism, specified in the TIP-072: Optimistic redemptions.

High-level architecture

The current byte size of the Bridge contract (~22 kB) is close to the limit. To leave some space for future Bridge upgrades, we decided to encapsulate the logic of the redemption veto mechanism in a separate upgradeable contract called RedemptionWatchtower, and attach it to the existing Bridge instance. Such a design has a positive impact on the Bridge size, nicely separates the concerns, and reduces the amount of direct changes in the living Bridge instance.

The RedemptionWatchtower contract acts as a central point for redemption guardians, manages vetoed redemptions, and provides other functionality specified in the TIP. It also serves as a source of information about vetoed redemptions, banned redeemers, and processing delays that should be preserved for specific redemption requests.

The chart below presents how the RedemptionWatchtower fits into the existing architecture and provides an overview of interactions between relevant smart contracts and system actors:

                                +---------------+
                                |               |
                      +---------+    Wallets    +-------------+
                      |         |               |             |
   pendingRedemptions |         +---------------+             | validateRedemptionProposal
                      |                                       |
                      |                                       |
                      v                                       v
+--------------------------+                          +-----------------------------+
|                          |     pendingRedemptions   |                             |
|          Bridge          |<-------------------------+   WalletProposalValidator   |
|                          |                          |                             |
+----+---------------------+                          +-------+---------------------+
     |                ^                                       |
     |                |                                       |
     |                |                                       |
     |                |                                       | getRedemptionDelay
     |                | notifyRedemptionVeto                  |
     |                +---------+                             |
     |                          |                             |
     |                          |                             |
     | isSafeRedemption    +----+---------------------+       |
     +-------------------->|                          |<------+
                           |   RedemptionWatchtower   |
                  +------->|                          |<------+
                  |        +--------------------------+       |
                  |                     ^                     |
                  |                     |                     |
                  |                     |                     |
   raiseObjection |                     | management          | security
                  |                     | actions             | actions
                  |                     |                     |
                  |                     |                     |
          +-------+-------+     +-------+-------+     +-------+-------+
          |               |     |               |     |               |
          |   Guardians   |     |    Manager    |     |     Owner     |
          |               |     |               |     |               |
          +---------------+     +---------------+     +---------------+

The RedemptionWatchtower contract

The RedemptionWatchtower contract interacts with several actors of the protocol. Each actor has a different set of capabilities:

Owner (Threshold Council)

The owner can call the following functions:

  • enableWatchtower which enables the veto mechanism for the first time. This function must set the watchtower's manager and can establish an initial set of guardians. This function also captures the timestamp of the call. This information is necessary to ensure the proper lifecycle of the veto mechanism (shut down after 18 months). It is also crucial for determining stalled redemptions that were created in the pre-veto era and can be vetoed indefinitely.
  • removeGuardian that can be used to remove specific guardians. This function is a safeguard against malicious guardians hence, it must be directly available to the owner.

Manager (Token holder DAO)

As per the TIP, most of the governance should be the authority of the Token holder DAO. To make it possible, we are introducing the role of the watchtower's manager who can use the following functions:

  • addGuardian which allows adding new redemption guardians
  • updateWatchtowerParameters that can update all governable parameters that steer the veto mechanism. Those parameters are redemption veto delays, veto time and financial penalties, and the mechanism lifetime.
  • unban which can be used to unban redeemers who were banned mistakenly. This is a safeguard for guardian mistakes that must be in place to protect honest redeemers.

Guardians

Guardians are the executors of the veto process. The only function they can call is raiseObjection. That function should be used to raise objections against specific redemption requests. Three subsequent objections lead to a redemption veto. Vetoed redemptions are not processed by the protocol, the requested amount is diminished by a penalty fee, and frozen for a specific time. Once the freeze period ends, the redeemer can claim those funds back. Moreover, redeemers whose redemptions were vetoed become banned and cannot ask for redemptions in the future. Last but not least, even a single objection (not leading to a veto) against a redemption (from a given wallet to a given BTC address) prevents asking the same wallet to redeem to the same BTC address in the future (this is similar to timed out redemptions).

Others

The RedemptionWatchtower exposes some functions available to the broad public. Those are:

  • isSafeRedemption which determines whether a redemption involving a specific wallet, BTC address, Bank's balance owner, and redeemer can be considered as safe. This function leverages the objections history and banned redeemers to determine so. A redemption is considered safe if neither the balance owner nor redeemer is banned and past redemptions from the given wallet to the given BTC address were not subject to guardian objections.
  • getRedemptionDelay that informs tBTC wallets about processing delays that should be preserved for specific redemption requests. Delays are determined based on raised objections.
  • withdrawVetoedFunds which can be used by redeemers to withdraw funds from vetoed redemptions once the freeze period ends.
  • disableWatchtower that can be used by anyone to disable the veto mechanism once the watchtower's lifetime elapses.

Changes in the Bridge contract

Integration of the RedemptionWatchtower contract with the existing Bridge incurs several changes in the latter.

First and foremost, the Bridge's state gains a new address field (redemptionWatchtower) that points to the RedemptionWatchtower contract. That field can be set using the new setRedemptionWatchtower function available for the Bridge's governance.

Secondly, the Bridge exposes a new notifyRedemptionVeto callback function. This function can be called only by the redemptionWatchtower address. The main responsibility of this function is propagating the consequences of a redemption veto to the Bridge's state, namely:

  • Reduce the pending redemptions value of the target wallet (supposed to handle the vetoed redemption). This is the same action as performed upon redemption timeout. This must be done because otherwise, the wallet would hold the reserve for a redemption request that would never be processed
  • Delete the redemption request from the pending redemptions mapping. This is important to avoid the vetoed redemption request being processed by the wallet or reported as timed out
  • Detain the redemption's request amount and transfer it under the control of the redemption watchtower for further processing (i.e. burn the penalty fee and allow withdrawal of the rest after the freeze period)

Last but not least, the Bridge leverages the redemptionWatchtower address to determine the safety of upcoming redemption requests. This is achieved using the isSafeRedemption call. This way, redemptions from banned redeemers (and balance owners) are blocked. The same applies to redemptions from specific wallets to specific BTC addresses which were subject to guardian objections in the past.

Changes in the WalletProposalValidator contract

The last piece of the puzzle is the integration of the veto mechanism with the off-chain tBTC wallets. Wallets must respect the new veto delay and not process redemptions during the period a redemption veto can still land. According to RFC-12, the tBTC wallets always consult the WalletProposalValidator to validate the ongoing redemption proposal before issuing the redemption transaction on the Bitcoin chain. That means it is enough to modify the WalletProposalValidator.validateRedemptionProposal function and take the veto delay into account there. The validateRedemptionProposal function calls the RedemptionWatchtower.getRedemptionDelay function for each redemption in the proposal and considers it valid only if the returned veto delay (counted since the redemption creation timestamp) already elapsed. This logic guarantees that a particular redemption proposal can only be considered valid if all of its redemption requests have surpassed their respective veto delay periods.

In light of the above, we should also prevent invalid redemption proposals (with redemptions violating the veto delay) from being issued by RFC-12 coordinators. An invalid proposal means a coordination window miss and the optimal strategy here is ensuring proposal validity at generation time. This requires adjustments in the off-chain redemption proposal generator logic. This work is beyond the scope of this pull request and will be addressed in a follow-up PR.

The ultimate protection against wallets not obeying the aforementioned rules is the fact that vetoed redemptions are removed from the pendingRedemption set in the Bridge. That means the Bridge will reject an SPV proof of a redemption transaction that handles at least one vetoed redemption request (that happens in the submitRedemptionProof function). In such a case, the given wallet will be deemed as fraudulent and punished according to the protocol rules.

Here we introduce the `RedemptionWatchtower` contract that will encapsulate
the logic of the redemption veto mechanism. This contract will be attached
to the `Bridge` contract upon the upcoming upgrade.
Here we implement functions allowing to enable the watchtower (i.e. veto
mechanism) and manage guardians.

The `enableWatchtower` function allows setting the watchtower manager and an
initial set of guardians. Moreover, we are capturing the initiation timestamp
which will be useful while determining pre-OR and post-OR redemption requests
and will be needed to implement the planned lifecycle of the veto mechanism

Regarding guardian management, we are adding two functions:
- `addGuardian` that can be called by the watchtower manager (Token Holder DAO)
- `removeGuardian` that can be called by the owner (Threshold Council)
Here we add all the state variables that must be implemented as part
of the `RedemptionWatchtower` contract. Specific variables and types
were determined during the prototype implementation phase.
Here we expose the `raiseObjection` function that allows guardians
object to specific redemption requests.

Each redemption has a default delay period during which the wallet is not
allowed to process it and the guardians can raise objections to. Each objection
extends the delay period by a certain amount of time. The third objection vetoes
the redemption request. This causes the redemption request to be rejected and
the redeemer to be penalized. Specific consequences of a veto are as follows:
- The redemption amount is frozen for a certain period of time,
- Once the freeze period expires, the redeemer can claim the frozen amount minus
  a penalty fee,
- The penalty fee is burned,
- The redeemer is banned from making future redemption requests.
Here we introduce the `VetoPeriodCheckOmitted` event that is emitted
when a redemption objection omits the veto period check. Such a case
occurs when the objection is related to a redemption created before
the watchtower was enabled.
Perform proposal and guardian checks first to fail fast and avoid
burning gas in case a guardian try to object again by mistake.
This flow is also more natural as the redemption request is checked
closer to the point of usage.
Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/7976725935 check.

From now on, the `Bridge` consults the `RedemptionWatchtower`
while a new redemption request arises. The redemption request
is allowed only if:
- The balance owner is not banned in the watchtower
- The redeemer is not banned in the watchtower
- The redemption key was not objected to in the past
@lukasz-zimnoch lukasz-zimnoch force-pushed the optimistic-redemption-1 branch from 9936af5 to c57f4f1 Compare February 20, 2024 17:02
Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/7977208120 check.

Copy link

@theref theref left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the plan with disableWatchtower? if the DAO let's the timeout pass then any user can disable the check?
if the DAO wanted to re-enable later on, would a new Watchtower have to be deployed?

…ator`

Wallets must respect the new veto delay and not process redemptions during the
period a redemption veto can still land. According to RFC-12, the tBTC wallets
always consult the `WalletProposalValidator` to validate the ongoing redemption
proposal before issuing the redemption transaction on the Bitcoin chain.
That means it is enough to modify the
`WalletProposalValidator.validateRedemptionProposal` function and take the
veto delay into account there. The `validateRedemptionProposal` function calls
the `RedemptionWatchtower.getRedemptionDelay` function for each redemption in
the proposal and considers it valid only if the returned veto delay
(counted since the redemption creation timestamp) already elapsed. This
logic guarantees that a particular redemption proposal can only be
considered valid if all of its redemption requests have surpassed their
respective veto delay periods.
Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/7988928374 check.

As part of the social contract, we are exposing the `disableWatchtower`
function that can be used by anyone to disable the veto mechanism
once the watchtower's lifetime expires (18 months by default).
Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/7989384985 check.

@lukasz-zimnoch
Copy link
Member Author

What's the plan with disableWatchtower? if the DAO let's the timeout pass then any user can disable the check? if the DAO wanted to re-enable later on, would a new Watchtower have to be deployed?

This is the part I just added, please see: 8d7d51b. This switch is kind of a social contract and disables the watchtower permanently by design. The DAO can vote to increase watchtowerLifetime if needed. If Threshold Council decides to re-enable a disabled watchtower, we can always add this ability in a future contract upgrade.

Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/7989442529 check.

Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/7989988248 check.

@lukasz-zimnoch lukasz-zimnoch force-pushed the optimistic-redemption-1 branch from 1785712 to d3cc2e8 Compare February 21, 2024 13:59
Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/7990218057 check.

This function is a safeguard in cases where honest redeemers are banned
due to guardians' mistake/malice.
Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/7990347255 check.

Here we expose the `withdrawVetoedFunds` allowing the redeemer to withdraw
their funds from vetoed redemption, once the freeze period expires.
Withdrawn amount is equal to the redemption requested amount diminished
by the current value of the penalty fee.
@lukasz-zimnoch lukasz-zimnoch marked this pull request as ready for review February 21, 2024 15:19
Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/7991382089 check.

event Unbanned(address indexed redeemer);

event VetoedFundsWithdrawn(
uint256 indexed redemptionkey,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
uint256 indexed redemptionkey,
uint256 indexed redemptionKey,

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! See 5346e0e

Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/8002611025 check.

require(
/* solhint-disable-next-line not-rely-on-time */
block.timestamp >
redemptionRequest.requestedAt + REDEMPTION_REQUEST_MIN_AGE,
block.timestamp > redemptionRequest.requestedAt + minAge,
Copy link
Contributor

@tomaszslabon tomaszslabon Feb 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check will prevent the wallet from processing certain redemption requests (the ones with some objections raised against them) for some time.
Are we sure this will not lead to a situation where somebody calls notifyRedemptionTimeout for a redemption that the wallet couldn't process on time because it had some objections?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure this will not lead to a situation where somebody calls notifyWalletRedemptionTimeout for a redemption that the wallet couldn't process because it had some objections?

Good point! This is not a problem as long as the redemption timeout is greater than the watchtower's level-two delay. In such a case, even if a redemption gets two objections, the wallet can process it before the timeout can be reported.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add this warning to the docs of the governable parameters controlling the redemption timeout?

Also, we probably want to update https://github.com/keep-network/tbtc-v2/tree/main/docs#parameters.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed as part of c6c03a3

lukasz-zimnoch added a commit to keep-network/keep-core that referenced this pull request Feb 22, 2024
The optimistic redemption upgrade introduces a veto mechanism that
enforces a processing delay on each redemption request. The exact
delay value depends on the number of objections raised against the given
redemption request. The `WalletProposalValidator` contract has been
modified to include validation of that delay factor. Here we introduce
the same for the redemption proposal generator. This ensures the generator
issues proposals that conform the on-chain validation rules and coordination
windows are not being wasted.

See: keep-network/tbtc-v2#788
tomaszslabon
tomaszslabon previously approved these changes Feb 23, 2024
Copy link

@vzotova vzotova left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first couple of questions on the way to understanding


VetoProposal storage veto = vetoProposals[redemptionKey];

uint8 requiredObjectionsCount = 3;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to make this variable as constant?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I missed it, good catch! Please see: 2556c28


if (vetoProposals[redemptionKey].objectionsCount > 0) {
return false;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question regarding this block, what happens in case only one or two objections were raised and then delay is expired?
I guess in that case redemption is still not safe but also new objections can't be raised?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such a redemption request is processed by the tBTC wallet after the delay. However, because there were objections to this redemption key (wallet + BTC address pair), the protocol blocks future redemptions from the same wallet to the given BTC address, just in case. Doing this is also easier from the redemption lifecycle management perspective and is consistent with what happens upon redemption timeout. That said:

  • In case of the happy path (redemption processed without troubles) we allow reusing the given redemption key and ask the same wallet to redeem to the same BTC address
  • In case of an unhappy path (objections raised, timeout hit) we block further usage of the given redemption key

I'm aware this may not be intuitive but this is a consequence of how tBTC identifies redemptions.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the explanation, I've found code where redemption handled after delay, could you point how redeemer banned in that case (one or two objections)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The redeemer is banned only after a full veto (3 objections). We don't ban after 1 or 2 objections.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That I saw, whole question is about 1 or 2 objections, got it

Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/8094151672 check.

Copy link

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/8094162362 check.

Copy link
Member

@pdyraga pdyraga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a high-level review of the Solidity, I was not looking at the tests.

I really like the design of having a separate watchtower to control the veto mechanism and having the watchtower to keep its balance in the Bank.

/// @param redemptionWatchtower Address of the redemption watchtower.
/// @dev Requirements:
/// - The caller must be the governance,
/// - Redemption watchtower address must not be already set,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not allow the governance to update the watchtower address? I see it is deployed as a proxy but still... We would avoid upgrading the Bridge contract in case the watchtower address needs to be replaced.

Copy link
Member Author

@lukasz-zimnoch lukasz-zimnoch Mar 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done on purpose to provide a kind of social contract regarding how the mechanism works. We do not expect to change anything in the mechanism itself. Any security upgrade would likely require a Bridge upgrade anyway. Additional argument is Bridge contract size. We do not add anything that is not a must have now.

Comment on lines 35 to 37
/// @param balanceOwner The address of the Bank balance owner whose balance
/// is getting redeemed.
/// @param redeemer The address that requested the redemption.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a little lost in what is the difference between those two. This will probably get clear as I move forward with the review of the rest of the code but could be an indicator we should improve the docs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah: I'd love to copy-paste the explanation of the redeemer from the requestRedemption function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed as part of c6c03a3

@@ -402,6 +433,19 @@ library Redemption {
bytes memory redeemerOutputScript,
uint64 amount
) internal {
if (self.redemptionWatchtower != address(0)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add this check to the @dev Requirements section?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed as part of c6c03a3

Comment on lines 1171 to 1173
// Capture the amount that should be transferred to the
// redemption watchtower.
uint64 detainedAmount = redemption.requestedAmount;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To confirm: we use the whole requested amount as a detained amount because the treasury fee is deducted in submitRedemptionProof. Since the redemption did not happen, the treasury fee was not deducted and we want to detain everything. Is this a correct understanding? Could be worth dropping a small comment here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this is correct. I will drop a comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed as part of c6c03a3

// to be processed by the wallet or reported as timed out.
delete self.pendingRedemptions[redemptionKey];

self.bank.transferBalance(self.redemptionWatchtower, detainedAmount);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice use of the Bank! Redemption Watchtower has a bank balance, I like it very much.

Comment on lines +623 to +625
if (delay > minAge) {
minAge = delay;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a moment I was thinking about whether we should not require the REDEMPTION_REQUEST_MIN_AGE to be much greater than the redemption delay in the watchtower. Think about this scenario: if they are the same, a second before the minimum age is reached, a guardian can send veto transaction in the mempool. Since it is still in the mempool, the wallet starts processing the redemption. Once the redemption happened on the Bitcoin side and before the proof was submitted on Ethereum, the veto transaction got mined.

Then I realized, we do not check for vetos when the redemption proof is submitted which lets us not to worry about this scenario. I like this setup but I think we should make it very clear for the future-us. Maybe drop a comment in the submitRedemptionProof function and/or write something in the docs?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed as part of c6c03a3

if (redemption.requestedAt >= watchtowerEnabledAt) {
require(
// Use < instead of <= to avoid a theoretical edge case
// where the delay is 0 (veto disabled) but three objections
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit confused by this part. We don't have the situation when veto is disabled, we only have two cases:

  • watchtower is completely disabled
  • the amount is below the veto/objection threshold.

Can we rephrase the part in the bracket a bit?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed as part of c6c03a3

Comment on lines +331 to +334
require(
redemption.requestedAt != 0,
"Redemption request does not exist"
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also handles the case when the redemption was already processed given we delete the pending request from the state in the Redemption.processNonChangeRedemptionTxOutput, correct? Can we drop a small comment about it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed as part of c6c03a3

require(
/* solhint-disable-next-line not-rely-on-time */
block.timestamp >
redemptionRequest.requestedAt + REDEMPTION_REQUEST_MIN_AGE,
block.timestamp > redemptionRequest.requestedAt + minAge,
"Redemption request min age not achieved yet"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this revert after reviewing the watchtower contract, I am not sure if the way we handle the delay is the right one. It should work but in case there was a delay increased as a result of an objection, we may end up with Redemption request min age not achieved yet which is not the case - the min age was achieved, it's just that this request is delayed given the veto. Not a blocker but it is something to think about.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm aware of it and I agree. However, this is the most low-effort solution we can implement here. Any alternative would complicate this already complicated on-chain validation. Hence I decided to do it this way.

Comment on lines +557 to +560
if (isBanned[balanceOwner]) {
return false;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what circumstances we ban the balance owner? I think I am still confused about the distinction between the balance owner and redeemer.

In the situation when someone redeems tBTC, I believe balanceOwner == TBTCVault.address and redeemer is the former tBTC holder. In case when someone redeems the Bank balance, balanceOwner == redeemer and this is the Bank balance owner.

In raiseObjection, we do isBanned[redemption.redeemer] = true;.

We never ban the balance owner to avoid the situation when the vault gets banned, we do ban the redeemer though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are blocking a case when a redeemer gets banned and tries to use that address as a balance source for redemption requested from another address. There is a path where you can allow someone to redeem from your balance, totally beyond TBTCVault.

Copy link

github-actions bot commented Mar 5, 2024

Solidity API documentation preview available in the artifacts of the https://github.com/keep-network/tbtc-v2/actions/runs/8159234335 check.

@tomaszslabon tomaszslabon merged commit f3f8d62 into main Mar 6, 2024
38 checks passed
@tomaszslabon tomaszslabon deleted the optimistic-redemption-1 branch March 6, 2024 09:26
tomaszslabon added a commit to keep-network/keep-core that referenced this pull request Mar 7, 2024
Refs: keep-network/tbtc-v2#781
Depends on: keep-network/tbtc-v2#788 (the
`client-build-test-publish` job will become green once 788 is merged and
a new `tbtc-v2@development` package with `RedemptionWatchtower` artifact
will be published to npm)

The optimistic redemption upgrade introduces a veto mechanism
(keep-network/tbtc-v2#788) that enforces a
processing delay on each redemption request. The exact delay value
depends on the number of objections raised against the given redemption
request. The `WalletProposalValidator` contract has been modified to
include validation of that delay factor. The first change
ed9c4ae introduces the same for the
redemption proposal generator. This ensures the generator issues
proposals that conform to the on-chain validation rules and coordination
windows are not being wasted.

By the way, we are taking an opportunity to optimize the deposit sweep
proposal generation. The `WalletProposalValidator` contract enforces the
minimum age of a deposit that can become part of the proposal. The
proposal generator
was missing this check and was often producing invalid proposals that
were violating the on-chain minimum deposit age rule. We fix that in
55be487.
@lukasz-zimnoch lukasz-zimnoch added this to the solidity/v1.6.0 milestone Mar 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⛓️ solidity Solidity contracts
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement basic redemptions veto mechanism (TIP-072)
5 participants