Skip to content

Commit da5c75c

Browse files
mswilkisonclaude
andcommitted
extraction: add ITBTCVaultMigrationDebt interface (compile-fix)
Bridge.sol on this branch imports `../vault/ITBTCVaultMigrationDebt.sol` (and references the interface's `hasOutstandingMigrationDebt.selector` via a fail-open staticcall) but the interface file was not extracted from the tlabs-xyz/tbtc umbrella into this canonical mirror. Both `contracts-format` and `contracts-slither` fail at compile-time with `HH404: File ... ITBTCVaultMigrationDebt.sol not found`. This commit pulls the interface file from umbrella as-is per the "import as-is first" rule. The 94-line file is a pure interface (events + function selectors, no external imports) so it drops in cleanly. Behavior: Bridge.sol's `hasOutstandingMigrationDebt.selector` staticcall is intentionally fail-open — if the vault doesn't implement the interface (which canonical TBTCVault doesn't yet), the guard is skipped. The full vault-side migration-debt implementation lands in a separate extraction PR (alongside ITBTCVaultMigrationSweepHook, ITBTCVaultMigrationSweepNotifier, TBTCMigrationDebtOperations). This PR remains [DO NOT MERGE - hard drain] per its title — post-drain operational prerequisites haven't been met. CI green just means the PR is review-ready for when the drain completes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3e5aee5 commit da5c75c

1 file changed

Lines changed: 94 additions & 0 deletions

File tree

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// SPDX-License-Identifier: GPL-3.0-only
2+
3+
pragma solidity 0.8.17;
4+
5+
/// @notice Interface for TBTCVault migration debt accounting.
6+
interface ITBTCVaultMigrationDebt {
7+
event MigrationDebtRegistered(address indexed revealer, uint256 amount);
8+
event MigrationDebtRepaid(address indexed revealer, uint256 remaining);
9+
event MigrationDebtCleared(address indexed revealer, uint256 amount);
10+
event MigrationRevealerSet(address indexed revealer, bool allowed);
11+
12+
/// @notice Registers the expected total migration debt for a revealer.
13+
/// Must be called before revealing migration-tagged deposits.
14+
/// The revealer cannot reveal migration deposits without an
15+
/// outstanding debt registration (enforced by
16+
/// `canRevealMigration`).
17+
/// @dev The `amount` parameter should represent the expected total BTC
18+
/// value of migration deposits for this revealer, converted to
19+
/// 1e18 Ethereum precision.
20+
///
21+
/// Amount convention trade-off: the caller must decide whether to
22+
/// register the gross (pre-fee) deposit value or an estimated net
23+
/// (post-fee) value:
24+
///
25+
/// Gross registration (registering the full pre-fee deposit
26+
/// amount): conservative approach. After the Bridge sweeps the
27+
/// deposit, it deducts a treasury fee per deposit
28+
/// (`depositAmount / depositTreasuryFeeDivisor`) and a share of
29+
/// the Bitcoin sweep transaction miner fee
30+
/// (`depositTxFeeIncurred`). The post-fee amount reaching the
31+
/// vault is less than the registered debt, leaving a residual
32+
/// positive debt. Migration lifecycle completion requires an
33+
/// owner-initiated `notifyMigrationSweep` call to transition
34+
/// the reserve to MIGRATED state. This approach avoids excess
35+
/// tBTC minting.
36+
///
37+
/// Net registration (estimating post-fee value): if the fee
38+
/// estimate matches actual deductions, debt reaches zero
39+
/// automatically on sweep and triggers the migration completion
40+
/// callback. However, the Bitcoin miner fee component is
41+
/// unknowable at registration time since it depends on the
42+
/// sweep batch composition and Bitcoin fee market conditions.
43+
/// Underestimating fees causes excess tBTC minting;
44+
/// overestimating fees leaves residual debt requiring owner
45+
/// intervention.
46+
///
47+
/// Registration is one-time: reverts if the revealer already has
48+
/// outstanding debt.
49+
/// @param revealer The address that will reveal migration-tagged
50+
/// deposits on the Bridge.
51+
/// @param amount Expected migration debt in 1e18 Ethereum precision
52+
/// (satoshi values are scaled by SATOSHI_MULTIPLIER = 10^10).
53+
function registerMigrationDebt(address revealer, uint256 amount) external;
54+
55+
function migrationDebt(address revealer) external view returns (uint256);
56+
57+
/// @notice Clears any remaining migration debt for `revealer`.
58+
/// @dev Intended for the over-registration residual-debt case once the
59+
/// migration lifecycle has been completed out-of-band and no further
60+
/// migration deposits should be revealed for this address.
61+
/// Implementations should zero the debt, update aggregate debt
62+
/// accounting, and disable migration reveals for `revealer`.
63+
/// @param revealer The revealer whose residual migration debt should be
64+
/// cleared.
65+
function clearMigrationDebt(address revealer) external;
66+
67+
function setMigrationRevealer(address revealer, bool allowed) external;
68+
69+
function isMigrationRevealer(address revealer)
70+
external
71+
view
72+
returns (bool);
73+
74+
/// @notice Returns whether the given revealer is allowed to reveal
75+
/// migration-tagged deposits.
76+
/// @dev Returns true only when both `isMigrationRevealer[revealer]`
77+
/// is set and `migrationDebt[revealer] > 0`. This ensures a
78+
/// revealer cannot reveal migration deposits without a
79+
/// corresponding debt registration, and cannot reveal beyond
80+
/// the registered capacity once debt is fully repaid.
81+
/// @param revealer Address to check migration reveal eligibility.
82+
/// @return True if the revealer can reveal migration deposits.
83+
function canRevealMigration(address revealer) external view returns (bool);
84+
85+
/// @notice Returns whether this vault has any outstanding migration debt
86+
/// across all revealers.
87+
/// @dev Implementations should maintain an internal counter that is
88+
/// incremented when migration debt is registered and decremented
89+
/// when a revealer's debt reaches zero, whether via repayment or an
90+
/// owner-authorized residual debt clear-out. This provides an O(1)
91+
/// aggregate query without enumerating individual revealers.
92+
/// @return True if at least one revealer has nonzero migration debt.
93+
function hasOutstandingMigrationDebt() external view returns (bool);
94+
}

0 commit comments

Comments
 (0)