From 3e3fc116c65144c2f8400f4fd5d4bf1d6446c89a Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Tue, 27 Feb 2024 12:20:45 +0100 Subject: [PATCH 1/4] Expose minimum deposit amount in AbstractDepositorContract Integrators may need minimum deposit amount to introduce validation if the amount user wants to deposit meets Bridge requirement of a deposit to exceed the dust threshold. --- .../integrator/AbstractTBTCDepositor.sol | 12 +++++++++++ solidity/contracts/test/TestTBTCDepositor.sol | 4 ++++ .../integrator/AbstractTBTCDepositor.test.ts | 20 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/solidity/contracts/integrator/AbstractTBTCDepositor.sol b/solidity/contracts/integrator/AbstractTBTCDepositor.sol index 7aeab8844..2b90a8326 100644 --- a/solidity/contracts/integrator/AbstractTBTCDepositor.sol +++ b/solidity/contracts/integrator/AbstractTBTCDepositor.sol @@ -289,4 +289,16 @@ abstract contract AbstractTBTCDepositor { ) .hash256View(); } + + /// @notice Returns minimum deposit amount. + /// @return Minimum deposit amount. In TBTC token decimals precision. + // slither-disable-next-line dead-code + function _minDepositAmount() internal view returns (uint256) { + // Read tBTC Bridge Deposit Dust Threshold in satoshi precision. + (uint64 bridgeDepositDustThresholdSat, , , ) = bridge + .depositParameters(); + + // Convert tBTC Bridge Deposit Dust Threshold to TBTC token precision. + return bridgeDepositDustThresholdSat * SATOSHI_MULTIPLIER; + } } diff --git a/solidity/contracts/test/TestTBTCDepositor.sol b/solidity/contracts/test/TestTBTCDepositor.sol index bf0a2d5ea..7ff342f75 100644 --- a/solidity/contracts/test/TestTBTCDepositor.sol +++ b/solidity/contracts/test/TestTBTCDepositor.sol @@ -51,6 +51,10 @@ contract TestTBTCDepositor is AbstractTBTCDepositor { ) external view returns (uint256) { return _calculateTbtcAmount(depositAmountSat, depositTreasuryFeeSat); } + + function minDepositAmountPublic() external view returns (uint256) { + return _minDepositAmount(); + } } contract MockBridge is IBridge { diff --git a/solidity/test/integrator/AbstractTBTCDepositor.test.ts b/solidity/test/integrator/AbstractTBTCDepositor.test.ts index 14b51c25f..e12841baa 100644 --- a/solidity/test/integrator/AbstractTBTCDepositor.test.ts +++ b/solidity/test/integrator/AbstractTBTCDepositor.test.ts @@ -438,4 +438,24 @@ describe("AbstractTBTCDepositor", () => { }) }) }) + + describe("_minDepositAmount", () => { + before(async () => { + await createSnapshot() + + // Set deposit dust threshold to 0.1 BTC. + await bridge.setDepositDustThreshold(1000000) + }) + + after(async () => { + await restoreSnapshot() + }) + + it("returns value in TBTC token precision", async () => { + // 1000000 sat * 1e10 TBTC + expect(await depositor.minDepositAmountPublic()).to.be.equal( + to1ePrecision(1000000, 10) + ) + }) + }) }) From c2d25910a5f4587355247df1033e9826cae48e80 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Tue, 27 Feb 2024 12:23:44 +0100 Subject: [PATCH 2/4] Remove unused import in test --- solidity/test/integrator/AbstractTBTCDepositor.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/solidity/test/integrator/AbstractTBTCDepositor.test.ts b/solidity/test/integrator/AbstractTBTCDepositor.test.ts index e12841baa..3af7633fd 100644 --- a/solidity/test/integrator/AbstractTBTCDepositor.test.ts +++ b/solidity/test/integrator/AbstractTBTCDepositor.test.ts @@ -9,7 +9,6 @@ import type { import { to1ePrecision } from "../helpers/contract-test-helpers" const { createSnapshot, restoreSnapshot } = helpers.snapshot -const { lastBlockTime } = helpers.time const loadFixture = (vault: string) => ({ fundingTx: { From ec3e81e068ff9629a5bf06f47bd4ba28c8472367 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Tue, 27 Feb 2024 12:39:37 +0100 Subject: [PATCH 3/4] Retrun initial deposit amount from _initializeDeposit function The amount may be useful for integrators for validations of the deposit amount. See example use case in https://github.com/thesis/acre/pull/253#discussion_r1500680454 It turns out that this version where we read from the storage costs `117 366` gas. Which is less than an alternative approach: ``` initialDepositAmount = fundingTx .outputVector .extractOutputAtIndex(reveal.fundingOutputIndex) .extractValue() * SATOSHI_MULTIPLIER; ``` which costs `117 601` gas. --- .../contracts/integrator/AbstractTBTCDepositor.sol | 10 +++++++--- solidity/contracts/test/TestTBTCDepositor.sol | 13 ++++++++++--- .../test/integrator/AbstractTBTCDepositor.test.ts | 4 +++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/solidity/contracts/integrator/AbstractTBTCDepositor.sol b/solidity/contracts/integrator/AbstractTBTCDepositor.sol index 2b90a8326..2f6f1af5b 100644 --- a/solidity/contracts/integrator/AbstractTBTCDepositor.sol +++ b/solidity/contracts/integrator/AbstractTBTCDepositor.sol @@ -123,6 +123,8 @@ abstract contract AbstractTBTCDepositor { /// `keccak256(fundingTxHash | reveal.fundingOutputIndex)`. This /// key can be used to refer to the deposit in the Bridge and /// TBTCVault contracts. + /// @return initialDepositAmount Amount of funding transaction deposit. In + /// TBTC token decimals precision. /// @dev Requirements: /// - The revealed vault address must match the TBTCVault address, /// - All requirements from {Bridge#revealDepositWithExtraData} @@ -134,10 +136,10 @@ abstract contract AbstractTBTCDepositor { IBridgeTypes.BitcoinTxInfo calldata fundingTx, IBridgeTypes.DepositRevealInfo calldata reveal, bytes32 extraData - ) internal returns (uint256) { + ) internal returns (uint256 depositKey, uint256 initialDepositAmount) { require(reveal.vault == address(tbtcVault), "Vault address mismatch"); - uint256 depositKey = _calculateDepositKey( + depositKey = _calculateDepositKey( _calculateBitcoinTxHash(fundingTx), reveal.fundingOutputIndex ); @@ -148,7 +150,9 @@ abstract contract AbstractTBTCDepositor { // an explicit check here. bridge.revealDepositWithExtraData(fundingTx, reveal, extraData); - return depositKey; + initialDepositAmount = + bridge.deposits(depositKey).amount * + SATOSHI_MULTIPLIER; } /// @notice Finalizes a deposit by calculating the amount of TBTC minted diff --git a/solidity/contracts/test/TestTBTCDepositor.sol b/solidity/contracts/test/TestTBTCDepositor.sol index 7ff342f75..a54155b11 100644 --- a/solidity/contracts/test/TestTBTCDepositor.sol +++ b/solidity/contracts/test/TestTBTCDepositor.sol @@ -11,7 +11,10 @@ import "../integrator/ITBTCVault.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract TestTBTCDepositor is AbstractTBTCDepositor { - event InitializeDepositReturned(uint256 depositKey); + event InitializeDepositReturned( + uint256 depositKey, + uint256 initialDepositAmount + ); event FinalizeDepositReturned( uint256 initialDepositAmount, @@ -28,8 +31,12 @@ contract TestTBTCDepositor is AbstractTBTCDepositor { IBridgeTypes.DepositRevealInfo calldata reveal, bytes32 extraData ) external { - uint256 depositKey = _initializeDeposit(fundingTx, reveal, extraData); - emit InitializeDepositReturned(depositKey); + (uint256 depositKey, uint256 initialDepositAmount) = _initializeDeposit( + fundingTx, + reveal, + extraData + ); + emit InitializeDepositReturned(depositKey, initialDepositAmount); } function finalizeDepositPublic(uint256 depositKey) external { diff --git a/solidity/test/integrator/AbstractTBTCDepositor.test.ts b/solidity/test/integrator/AbstractTBTCDepositor.test.ts index 3af7633fd..fda52941f 100644 --- a/solidity/test/integrator/AbstractTBTCDepositor.test.ts +++ b/solidity/test/integrator/AbstractTBTCDepositor.test.ts @@ -108,6 +108,8 @@ describe("AbstractTBTCDepositor", () => { }) context("when deposit is accepted by the Bridge", () => { + const expectedInitialDepositAmount = to1ePrecision(10000, 10) + let tx: ContractTransaction before(async () => { @@ -133,7 +135,7 @@ describe("AbstractTBTCDepositor", () => { it("should return proper values", async () => { await expect(tx) .to.emit(depositor, "InitializeDepositReturned") - .withArgs(fixture.expectedDepositKey) + .withArgs(fixture.expectedDepositKey, expectedInitialDepositAmount) }) }) }) From a3a7cf6b97139fc3af4e57523c7ccade68354d69 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 28 Feb 2024 11:52:31 +0100 Subject: [PATCH 4/4] Update example usage in docs for _initializeDeposit _initializeDeposit now returns additional property: initialDepositAmount. We need to update the usage example. --- solidity/contracts/integrator/AbstractTBTCDepositor.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solidity/contracts/integrator/AbstractTBTCDepositor.sol b/solidity/contracts/integrator/AbstractTBTCDepositor.sol index 2f6f1af5b..0ba4928ba 100644 --- a/solidity/contracts/integrator/AbstractTBTCDepositor.sol +++ b/solidity/contracts/integrator/AbstractTBTCDepositor.sol @@ -54,7 +54,7 @@ import "./ITBTCVault.sol"; /// // Embed necessary context as extra data. /// bytes32 extraData = ...; /// -/// uint256 depositKey = _initializeDeposit( +/// (uint256 depositKey, uint256 initialDepositAmount) = _initializeDeposit( /// fundingTx, /// reveal, /// extraData