@keep-network/tbtc-v2 0.1.1-dev.32 → 0.1.1-dev.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/artifacts/TBTC.json +3 -3
- package/artifacts/TBTCToken.json +3 -3
- package/artifacts/VendingMachine.json +10 -10
- package/artifacts/solcInputs/{590fbe282bf8b630b15f2da419b402f1.json → 922339b8aca537314dc3d35162317588.json} +14 -2
- package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
- package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
- package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
- package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
- package/build/contracts/bridge/Bridge.sol/Bridge.json +141 -150
- package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +4 -0
- package/build/contracts/bridge/BridgeState.sol/BridgeState.json +10 -0
- package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +4 -0
- package/build/contracts/bridge/Deposit.sol/Deposit.json +72 -0
- package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +1 -1
- package/build/contracts/bridge/Frauds.sol/Frauds.dbg.json +1 -1
- package/build/contracts/bridge/Frauds.sol/Frauds.json +2 -2
- package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +4 -0
- package/build/contracts/bridge/{Bridge.sol → IRelay.sol}/IRelay.json +1 -1
- package/build/contracts/bridge/Sweep.sol/Sweep.dbg.json +4 -0
- package/build/contracts/bridge/Sweep.sol/Sweep.json +48 -0
- package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
- package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +1 -1
- package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
- package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
- package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
- package/contracts/bridge/Bridge.sol +116 -686
- package/contracts/bridge/BridgeState.sol +104 -0
- package/contracts/bridge/Deposit.sol +247 -0
- package/contracts/bridge/IRelay.sol +28 -0
- package/contracts/bridge/Sweep.sol +510 -0
- package/package.json +1 -1
- package/build/contracts/bridge/Bridge.sol/IRelay.dbg.json +0 -4
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
// ██████████████ ▐████▌ ██████████████
|
|
4
|
+
// ██████████████ ▐████▌ ██████████████
|
|
5
|
+
// ▐████▌ ▐████▌
|
|
6
|
+
// ▐████▌ ▐████▌
|
|
7
|
+
// ██████████████ ▐████▌ ██████████████
|
|
8
|
+
// ██████████████ ▐████▌ ██████████████
|
|
9
|
+
// ▐████▌ ▐████▌
|
|
10
|
+
// ▐████▌ ▐████▌
|
|
11
|
+
// ▐████▌ ▐████▌
|
|
12
|
+
// ▐████▌ ▐████▌
|
|
13
|
+
// ▐████▌ ▐████▌
|
|
14
|
+
// ▐████▌ ▐████▌
|
|
15
|
+
|
|
16
|
+
pragma solidity ^0.8.9;
|
|
17
|
+
|
|
18
|
+
import "./IRelay.sol";
|
|
19
|
+
import "./Deposit.sol";
|
|
20
|
+
|
|
21
|
+
import "../bank/Bank.sol";
|
|
22
|
+
|
|
23
|
+
library BridgeState {
|
|
24
|
+
struct Storage {
|
|
25
|
+
/// @notice The number of confirmations on the Bitcoin chain required to
|
|
26
|
+
/// successfully evaluate an SPV proof.
|
|
27
|
+
uint256 txProofDifficultyFactor;
|
|
28
|
+
/// TODO: Revisit whether it should be governable or not.
|
|
29
|
+
/// @notice Address of the Bank this Bridge belongs to.
|
|
30
|
+
Bank bank;
|
|
31
|
+
/// TODO: Make it governable.
|
|
32
|
+
/// @notice Bitcoin relay providing the current Bitcoin network
|
|
33
|
+
/// difficulty.
|
|
34
|
+
IRelay relay;
|
|
35
|
+
/// TODO: Revisit whether it should be governable or not.
|
|
36
|
+
/// @notice Address where the deposit and redemption treasury fees will
|
|
37
|
+
/// be sent to. Treasury takes part in the operators rewarding
|
|
38
|
+
/// process.
|
|
39
|
+
address treasury;
|
|
40
|
+
/// TODO: Make it governable.
|
|
41
|
+
/// @notice The minimal amount that can be requested to deposit.
|
|
42
|
+
/// Value of this parameter must take into account the value of
|
|
43
|
+
/// `depositTreasuryFeeDivisor` and `depositTxMaxFee`
|
|
44
|
+
/// parameters in order to make requests that can incur the
|
|
45
|
+
/// treasury and transaction fee and still satisfy the depositor.
|
|
46
|
+
uint64 depositDustThreshold;
|
|
47
|
+
/// TODO: Make it governable.
|
|
48
|
+
/// @notice Divisor used to compute the treasury fee taken from each
|
|
49
|
+
/// deposit and transferred to the treasury upon sweep proof
|
|
50
|
+
/// submission. That fee is computed as follows:
|
|
51
|
+
/// `treasuryFee = depositedAmount / depositTreasuryFeeDivisor`
|
|
52
|
+
/// For example, if the treasury fee needs to be 2% of each deposit,
|
|
53
|
+
/// the `depositTreasuryFeeDivisor` should be set to `50`
|
|
54
|
+
/// because `1/50 = 0.02 = 2%`.
|
|
55
|
+
uint64 depositTreasuryFeeDivisor;
|
|
56
|
+
/// TODO: Make it governable.
|
|
57
|
+
/// @notice Maximum amount of BTC transaction fee that can be incurred by
|
|
58
|
+
/// each swept deposit being part of the given sweep
|
|
59
|
+
/// transaction. If the maximum BTC transaction fee is exceeded,
|
|
60
|
+
/// such transaction is considered a fraud.
|
|
61
|
+
/// @dev This is a per-deposit input max fee for the sweep transaction.
|
|
62
|
+
uint64 depositTxMaxFee;
|
|
63
|
+
/// @notice Collection of all revealed deposits indexed by
|
|
64
|
+
/// keccak256(fundingTxHash | fundingOutputIndex).
|
|
65
|
+
/// The fundingTxHash is bytes32 (ordered as in Bitcoin internally)
|
|
66
|
+
/// and fundingOutputIndex an uint32. This mapping may contain valid
|
|
67
|
+
/// and invalid deposits and the wallet is responsible for
|
|
68
|
+
/// validating them before attempting to execute a sweep.
|
|
69
|
+
mapping(uint256 => Deposit.Request) deposits;
|
|
70
|
+
/// @notice Indicates if the vault with the given address is trusted or not.
|
|
71
|
+
/// Depositors can route their revealed deposits only to trusted
|
|
72
|
+
/// vaults and have trusted vaults notified about new deposits as
|
|
73
|
+
/// soon as these deposits get swept. Vaults not trusted by the
|
|
74
|
+
/// Bridge can still be used by Bank balance owners on their own
|
|
75
|
+
/// responsibility - anyone can approve their Bank balance to any
|
|
76
|
+
/// address.
|
|
77
|
+
mapping(address => bool) isVaultTrusted;
|
|
78
|
+
/// @notice Collection of main UTXOs that are honestly spent indexed by
|
|
79
|
+
/// keccak256(fundingTxHash | fundingOutputIndex). The fundingTxHash
|
|
80
|
+
/// is bytes32 (ordered as in Bitcoin internally) and
|
|
81
|
+
/// fundingOutputIndex an uint32. A main UTXO is considered honestly
|
|
82
|
+
/// spent if it was used as an input of a transaction that have been
|
|
83
|
+
/// proven in the Bridge.
|
|
84
|
+
mapping(uint256 => bool) spentMainUTXOs;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// TODO: Is it the right place for this function? Should we move it to Bridge?
|
|
88
|
+
/// @notice Determines the current Bitcoin SPV proof difficulty context.
|
|
89
|
+
/// @return proofDifficulty Bitcoin proof difficulty context.
|
|
90
|
+
function proofDifficultyContext(Storage storage self)
|
|
91
|
+
internal
|
|
92
|
+
view
|
|
93
|
+
returns (BitcoinTx.ProofDifficulty memory proofDifficulty)
|
|
94
|
+
{
|
|
95
|
+
IRelay relay = self.relay;
|
|
96
|
+
proofDifficulty.currentEpochDifficulty = relay
|
|
97
|
+
.getCurrentEpochDifficulty();
|
|
98
|
+
proofDifficulty.previousEpochDifficulty = relay
|
|
99
|
+
.getPrevEpochDifficulty();
|
|
100
|
+
proofDifficulty.difficultyFactor = self.txProofDifficultyFactor;
|
|
101
|
+
|
|
102
|
+
return proofDifficulty;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
// ██████████████ ▐████▌ ██████████████
|
|
4
|
+
// ██████████████ ▐████▌ ██████████████
|
|
5
|
+
// ▐████▌ ▐████▌
|
|
6
|
+
// ▐████▌ ▐████▌
|
|
7
|
+
// ██████████████ ▐████▌ ██████████████
|
|
8
|
+
// ██████████████ ▐████▌ ██████████████
|
|
9
|
+
// ▐████▌ ▐████▌
|
|
10
|
+
// ▐████▌ ▐████▌
|
|
11
|
+
// ▐████▌ ▐████▌
|
|
12
|
+
// ▐████▌ ▐████▌
|
|
13
|
+
// ▐████▌ ▐████▌
|
|
14
|
+
// ▐████▌ ▐████▌
|
|
15
|
+
|
|
16
|
+
pragma solidity ^0.8.9;
|
|
17
|
+
|
|
18
|
+
import {BTCUtils} from "@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol";
|
|
19
|
+
import {BytesLib} from "@keep-network/bitcoin-spv-sol/contracts/BytesLib.sol";
|
|
20
|
+
|
|
21
|
+
import "./BitcoinTx.sol";
|
|
22
|
+
import "./BridgeState.sol";
|
|
23
|
+
import "./Wallets.sol";
|
|
24
|
+
|
|
25
|
+
library Deposit {
|
|
26
|
+
using Wallets for Wallets.Data;
|
|
27
|
+
|
|
28
|
+
using BTCUtils for bytes;
|
|
29
|
+
using BytesLib for bytes;
|
|
30
|
+
|
|
31
|
+
/// @notice Represents data which must be revealed by the depositor during
|
|
32
|
+
/// deposit reveal.
|
|
33
|
+
struct RevealInfo {
|
|
34
|
+
// Index of the funding output belonging to the funding transaction.
|
|
35
|
+
uint32 fundingOutputIndex;
|
|
36
|
+
// Ethereum depositor address.
|
|
37
|
+
address depositor;
|
|
38
|
+
// The blinding factor as 8 bytes. Byte endianness doesn't matter
|
|
39
|
+
// as this factor is not interpreted as uint.
|
|
40
|
+
bytes8 blindingFactor;
|
|
41
|
+
// The compressed Bitcoin public key (33 bytes and 02 or 03 prefix)
|
|
42
|
+
// of the deposit's wallet hashed in the HASH160 Bitcoin opcode style.
|
|
43
|
+
bytes20 walletPubKeyHash;
|
|
44
|
+
// The compressed Bitcoin public key (33 bytes and 02 or 03 prefix)
|
|
45
|
+
// that can be used to make the deposit refund after the refund
|
|
46
|
+
// locktime passes. Hashed in the HASH160 Bitcoin opcode style.
|
|
47
|
+
bytes20 refundPubKeyHash;
|
|
48
|
+
// The refund locktime (4-byte LE). Interpreted according to locktime
|
|
49
|
+
// parsing rules described in:
|
|
50
|
+
// https://developer.bitcoin.org/devguide/transactions.html#locktime-and-sequence-number
|
|
51
|
+
// and used with OP_CHECKLOCKTIMEVERIFY opcode as described in:
|
|
52
|
+
// https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki
|
|
53
|
+
bytes4 refundLocktime;
|
|
54
|
+
// Address of the Bank vault to which the deposit is routed to.
|
|
55
|
+
// Optional, can be 0x0. The vault must be trusted by the Bridge.
|
|
56
|
+
address vault;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// @notice Represents tBTC deposit request data.
|
|
60
|
+
struct Request {
|
|
61
|
+
// Ethereum depositor address.
|
|
62
|
+
address depositor;
|
|
63
|
+
// Deposit amount in satoshi.
|
|
64
|
+
uint64 amount;
|
|
65
|
+
// UNIX timestamp the deposit was revealed at.
|
|
66
|
+
uint32 revealedAt;
|
|
67
|
+
// Address of the Bank vault the deposit is routed to.
|
|
68
|
+
// Optional, can be 0x0.
|
|
69
|
+
address vault;
|
|
70
|
+
// Treasury TBTC fee in satoshi at the moment of deposit reveal.
|
|
71
|
+
uint64 treasuryFee;
|
|
72
|
+
// UNIX timestamp the deposit was swept at. Note this is not the
|
|
73
|
+
// time when the deposit was swept on the Bitcoin chain but actually
|
|
74
|
+
// the time when the sweep proof was delivered to the Ethereum chain.
|
|
75
|
+
uint32 sweptAt;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
event DepositRevealed(
|
|
79
|
+
bytes32 fundingTxHash,
|
|
80
|
+
uint32 fundingOutputIndex,
|
|
81
|
+
address depositor,
|
|
82
|
+
uint64 amount,
|
|
83
|
+
bytes8 blindingFactor,
|
|
84
|
+
bytes20 walletPubKeyHash,
|
|
85
|
+
bytes20 refundPubKeyHash,
|
|
86
|
+
bytes4 refundLocktime,
|
|
87
|
+
address vault
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
/// @notice Used by the depositor to reveal information about their P2(W)SH
|
|
91
|
+
/// Bitcoin deposit to the Bridge on Ethereum chain. The off-chain
|
|
92
|
+
/// wallet listens for revealed deposit events and may decide to
|
|
93
|
+
/// include the revealed deposit in the next executed sweep.
|
|
94
|
+
/// Information about the Bitcoin deposit can be revealed before or
|
|
95
|
+
/// after the Bitcoin transaction with P2(W)SH deposit is mined on
|
|
96
|
+
/// the Bitcoin chain. Worth noting, the gas cost of this function
|
|
97
|
+
/// scales with the number of P2(W)SH transaction inputs and
|
|
98
|
+
/// outputs. The deposit may be routed to one of the trusted vaults.
|
|
99
|
+
/// When a deposit is routed to a vault, vault gets notified when
|
|
100
|
+
/// the deposit gets swept and it may execute the appropriate action.
|
|
101
|
+
/// @param fundingTx Bitcoin funding transaction data, see `BitcoinTx.Info`
|
|
102
|
+
/// @param reveal Deposit reveal data, see `RevealInfo struct
|
|
103
|
+
/// @dev Requirements:
|
|
104
|
+
/// - `reveal.walletPubKeyHash` must identify a `Live` wallet
|
|
105
|
+
/// - `reveal.vault` must be 0x0 or point to a trusted vault
|
|
106
|
+
/// - `reveal.fundingOutputIndex` must point to the actual P2(W)SH
|
|
107
|
+
/// output of the BTC deposit transaction
|
|
108
|
+
/// - `reveal.depositor` must be the Ethereum address used in the
|
|
109
|
+
/// P2(W)SH BTC deposit transaction,
|
|
110
|
+
/// - `reveal.blindingFactor` must be the blinding factor used in the
|
|
111
|
+
/// P2(W)SH BTC deposit transaction,
|
|
112
|
+
/// - `reveal.walletPubKeyHash` must be the wallet pub key hash used in
|
|
113
|
+
/// the P2(W)SH BTC deposit transaction,
|
|
114
|
+
/// - `reveal.refundPubKeyHash` must be the refund pub key hash used in
|
|
115
|
+
/// the P2(W)SH BTC deposit transaction,
|
|
116
|
+
/// - `reveal.refundLocktime` must be the refund locktime used in the
|
|
117
|
+
/// P2(W)SH BTC deposit transaction,
|
|
118
|
+
/// - BTC deposit for the given `fundingTxHash`, `fundingOutputIndex`
|
|
119
|
+
/// can be revealed only one time.
|
|
120
|
+
///
|
|
121
|
+
/// If any of these requirements is not met, the wallet _must_ refuse
|
|
122
|
+
/// to sweep the deposit and the depositor has to wait until the
|
|
123
|
+
/// deposit script unlocks to receive their BTC back.
|
|
124
|
+
function revealDeposit(
|
|
125
|
+
BridgeState.Storage storage self,
|
|
126
|
+
Wallets.Data storage wallets,
|
|
127
|
+
BitcoinTx.Info calldata fundingTx,
|
|
128
|
+
RevealInfo calldata reveal
|
|
129
|
+
) external {
|
|
130
|
+
require(
|
|
131
|
+
wallets.registeredWallets[reveal.walletPubKeyHash].state ==
|
|
132
|
+
Wallets.WalletState.Live,
|
|
133
|
+
"Wallet is not in Live state"
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
require(
|
|
137
|
+
reveal.vault == address(0) || self.isVaultTrusted[reveal.vault],
|
|
138
|
+
"Vault is not trusted"
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
// TODO: Should we enforce a specific locktime at contract level?
|
|
142
|
+
|
|
143
|
+
bytes memory expectedScript = abi.encodePacked(
|
|
144
|
+
hex"14", // Byte length of depositor Ethereum address.
|
|
145
|
+
reveal.depositor,
|
|
146
|
+
hex"75", // OP_DROP
|
|
147
|
+
hex"08", // Byte length of blinding factor value.
|
|
148
|
+
reveal.blindingFactor,
|
|
149
|
+
hex"75", // OP_DROP
|
|
150
|
+
hex"76", // OP_DUP
|
|
151
|
+
hex"a9", // OP_HASH160
|
|
152
|
+
hex"14", // Byte length of a compressed Bitcoin public key hash.
|
|
153
|
+
reveal.walletPubKeyHash,
|
|
154
|
+
hex"87", // OP_EQUAL
|
|
155
|
+
hex"63", // OP_IF
|
|
156
|
+
hex"ac", // OP_CHECKSIG
|
|
157
|
+
hex"67", // OP_ELSE
|
|
158
|
+
hex"76", // OP_DUP
|
|
159
|
+
hex"a9", // OP_HASH160
|
|
160
|
+
hex"14", // Byte length of a compressed Bitcoin public key hash.
|
|
161
|
+
reveal.refundPubKeyHash,
|
|
162
|
+
hex"88", // OP_EQUALVERIFY
|
|
163
|
+
hex"04", // Byte length of refund locktime value.
|
|
164
|
+
reveal.refundLocktime,
|
|
165
|
+
hex"b1", // OP_CHECKLOCKTIMEVERIFY
|
|
166
|
+
hex"75", // OP_DROP
|
|
167
|
+
hex"ac", // OP_CHECKSIG
|
|
168
|
+
hex"68" // OP_ENDIF
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
bytes memory fundingOutput = fundingTx
|
|
172
|
+
.outputVector
|
|
173
|
+
.extractOutputAtIndex(reveal.fundingOutputIndex);
|
|
174
|
+
bytes memory fundingOutputHash = fundingOutput.extractHash();
|
|
175
|
+
|
|
176
|
+
if (fundingOutputHash.length == 20) {
|
|
177
|
+
// A 20-byte output hash is used by P2SH. That hash is constructed
|
|
178
|
+
// by applying OP_HASH160 on the locking script. A 20-byte output
|
|
179
|
+
// hash is used as well by P2PKH and P2WPKH (OP_HASH160 on the
|
|
180
|
+
// public key). However, since we compare the actual output hash
|
|
181
|
+
// with an expected locking script hash, this check will succeed only
|
|
182
|
+
// for P2SH transaction type with expected script hash value. For
|
|
183
|
+
// P2PKH and P2WPKH, it will fail on the output hash comparison with
|
|
184
|
+
// the expected locking script hash.
|
|
185
|
+
require(
|
|
186
|
+
fundingOutputHash.slice20(0) == expectedScript.hash160View(),
|
|
187
|
+
"Wrong 20-byte script hash"
|
|
188
|
+
);
|
|
189
|
+
} else if (fundingOutputHash.length == 32) {
|
|
190
|
+
// A 32-byte output hash is used by P2WSH. That hash is constructed
|
|
191
|
+
// by applying OP_SHA256 on the locking script.
|
|
192
|
+
require(
|
|
193
|
+
fundingOutputHash.toBytes32() == sha256(expectedScript),
|
|
194
|
+
"Wrong 32-byte script hash"
|
|
195
|
+
);
|
|
196
|
+
} else {
|
|
197
|
+
revert("Wrong script hash length");
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Resulting TX hash is in native Bitcoin little-endian format.
|
|
201
|
+
bytes32 fundingTxHash = abi
|
|
202
|
+
.encodePacked(
|
|
203
|
+
fundingTx.version,
|
|
204
|
+
fundingTx.inputVector,
|
|
205
|
+
fundingTx.outputVector,
|
|
206
|
+
fundingTx.locktime
|
|
207
|
+
)
|
|
208
|
+
.hash256View();
|
|
209
|
+
|
|
210
|
+
Request storage deposit = self.deposits[
|
|
211
|
+
uint256(
|
|
212
|
+
keccak256(
|
|
213
|
+
abi.encodePacked(fundingTxHash, reveal.fundingOutputIndex)
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
];
|
|
217
|
+
require(deposit.revealedAt == 0, "Deposit already revealed");
|
|
218
|
+
|
|
219
|
+
uint64 fundingOutputAmount = fundingOutput.extractValue();
|
|
220
|
+
|
|
221
|
+
require(
|
|
222
|
+
fundingOutputAmount >= self.depositDustThreshold,
|
|
223
|
+
"Deposit amount too small"
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
deposit.amount = fundingOutputAmount;
|
|
227
|
+
deposit.depositor = reveal.depositor;
|
|
228
|
+
/* solhint-disable-next-line not-rely-on-time */
|
|
229
|
+
deposit.revealedAt = uint32(block.timestamp);
|
|
230
|
+
deposit.vault = reveal.vault;
|
|
231
|
+
deposit.treasuryFee = self.depositTreasuryFeeDivisor > 0
|
|
232
|
+
? fundingOutputAmount / self.depositTreasuryFeeDivisor
|
|
233
|
+
: 0;
|
|
234
|
+
|
|
235
|
+
emit DepositRevealed(
|
|
236
|
+
fundingTxHash,
|
|
237
|
+
reveal.fundingOutputIndex,
|
|
238
|
+
reveal.depositor,
|
|
239
|
+
fundingOutputAmount,
|
|
240
|
+
reveal.blindingFactor,
|
|
241
|
+
reveal.walletPubKeyHash,
|
|
242
|
+
reveal.refundPubKeyHash,
|
|
243
|
+
reveal.refundLocktime,
|
|
244
|
+
reveal.vault
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
// ██████████████ ▐████▌ ██████████████
|
|
4
|
+
// ██████████████ ▐████▌ ██████████████
|
|
5
|
+
// ▐████▌ ▐████▌
|
|
6
|
+
// ▐████▌ ▐████▌
|
|
7
|
+
// ██████████████ ▐████▌ ██████████████
|
|
8
|
+
// ██████████████ ▐████▌ ██████████████
|
|
9
|
+
// ▐████▌ ▐████▌
|
|
10
|
+
// ▐████▌ ▐████▌
|
|
11
|
+
// ▐████▌ ▐████▌
|
|
12
|
+
// ▐████▌ ▐████▌
|
|
13
|
+
// ▐████▌ ▐████▌
|
|
14
|
+
// ▐████▌ ▐████▌
|
|
15
|
+
|
|
16
|
+
pragma solidity ^0.8.9;
|
|
17
|
+
|
|
18
|
+
/// @title Interface for the Bitcoin relay
|
|
19
|
+
/// @notice Contains only the methods needed by tBTC v2. The Bitcoin relay
|
|
20
|
+
/// provides the difficulty of the previous and current epoch. One
|
|
21
|
+
/// difficulty epoch spans 2016 blocks.
|
|
22
|
+
interface IRelay {
|
|
23
|
+
/// @notice Returns the difficulty of the current epoch.
|
|
24
|
+
function getCurrentEpochDifficulty() external view returns (uint256);
|
|
25
|
+
|
|
26
|
+
/// @notice Returns the difficulty of the previous epoch.
|
|
27
|
+
function getPrevEpochDifficulty() external view returns (uint256);
|
|
28
|
+
}
|