Skip to content

Commit

Permalink
Expose deposit amounts in AbstractDepositorContract (#791)
Browse files Browse the repository at this point in the history
In this PR we introduce two changes to the AbstractDepositorContract
around the deposit amounts.

### Expose minimum deposit amount
Integrators may need a minimum deposit amount to introduce validation if
the amount the user wants to deposit meets the Bridge requirement of a
deposit to exceed the dust threshold.
Originally proposed in
thesis/acre#253 (comment).

### Return initial deposit amount from _initializeDeposit function

The amount may be useful for integrators for validations of the deposit
amount. Originally proposed in
thesis/acre#253 (comment).
    
It turns out that this version where we read from the storage:
```solidity
        initialDepositAmount =
            bridge.deposits(depositKey).amount *
            SATOSHI_MULTIPLIER;
```
 costs `117 366` gas.
Which is less than an alternative approach:
```solidity
            initialDepositAmount =
                fundingTx
                    .outputVector
                    .extractOutputAtIndex(reveal.fundingOutputIndex)
                    .extractValue() *
                SATOSHI_MULTIPLIER;
```
which costs `117 601` gas.

We return `initialDepositAmount` from two functions:
`_initializeDeposit` and `_finalizeDeposit`. I tried to introduce a
getter function:
```solidity
    function _getInitialDepositAmount(
        uint256 depositKey
    ) internal view returns (uint256) {
        IBridgeTypes.DepositRequest memory deposit = bridge.deposits(
            depositKey
        );
        require(deposit.revealedAt != 0, "Deposit not initialized");

        return deposit.amount * SATOSHI_MULTIPLIER;
    }
```
and removed `initialDepositAmount` return from `_initializeDeposit` and
`_finalizeDeposit` functions.
Unfortunately, the overall cost in the reference BitcoinDepositor
implementation from thesis/acre#253 wasn't
improved:
BEFORE:
```
+ initializeStake --> 143 004
+ finalizeStake --> 195 178
= total --> 338 182
```
AFTER:
```
+ initializeStake --> 142 912
+ finalizeStake --> 197 960
= total --> 340 872
```
  • Loading branch information
lukasz-zimnoch authored Feb 28, 2024
2 parents edef923 + a3a7cf6 commit 9e047d1
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 9 deletions.
24 changes: 20 additions & 4 deletions solidity/contracts/integrator/AbstractTBTCDepositor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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}
Expand All @@ -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
);
Expand All @@ -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
Expand Down Expand Up @@ -289,4 +293,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;
}
}
17 changes: 14 additions & 3 deletions solidity/contracts/test/TestTBTCDepositor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 {
Expand All @@ -51,6 +58,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 {
Expand Down
25 changes: 23 additions & 2 deletions solidity/test/integrator/AbstractTBTCDepositor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -109,6 +108,8 @@ describe("AbstractTBTCDepositor", () => {
})

context("when deposit is accepted by the Bridge", () => {
const expectedInitialDepositAmount = to1ePrecision(10000, 10)

let tx: ContractTransaction

before(async () => {
Expand All @@ -134,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)
})
})
})
Expand Down Expand Up @@ -438,4 +439,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)
)
})
})
})

0 comments on commit 9e047d1

Please sign in to comment.