diff --git a/sdk/src/lib/contracts/bitcoin-depositor.ts b/sdk/src/lib/contracts/bitcoin-depositor.ts index 05d3dd887..baa71a770 100644 --- a/sdk/src/lib/contracts/bitcoin-depositor.ts +++ b/sdk/src/lib/contracts/bitcoin-depositor.ts @@ -9,6 +9,44 @@ export type DecodedExtraData = { referral: number } +/** + * Represents the tBTC network minting fees. + */ +type TBTCMintingFees = { + /** + * The tBTC treasury fee taken from each deposit and transferred to the + * treasury upon sweep proof submission. Is calculated based on the initial + * funding transaction amount. + */ + treasuryFee: bigint + /** + * The tBTC optimistic minting fee, Is calculated AFTER the treasury fee is + * cut. + */ + optimisticMintingFee: bigint + /** + * Maximum amount of BTC transaction fee that can be incurred by each swept + * deposit being part of the given sweep transaction. + */ + depositTxMaxFee: bigint +} + +/** + * Represents the Acre protocol deposit fees. + */ +type AcreDepositFees = { + /** + * The Acre protocol depositor fee taken from each Bitcoin deposit and + * transferred to the treasury upon deposit request finalization. + */ + bitcoinDepositorFee: bigint +} + +export type DepositFees = { + tbtc: TBTCMintingFees + acre: AcreDepositFees +} + /** * Interface for communication with the BitcoinDepositor on-chain contract. */ @@ -36,6 +74,14 @@ export interface BitcoinDepositor extends DepositorProxy { */ decodeExtraData(extraData: string): DecodedExtraData + /** + * Calculates the deposit fee based on the provided amount. + * @param amountToDeposit Amount to deposit in 1e18 token precision. + * @returns Deposit fees grouped by tBTC and Acre networks in 1e18 tBTC token + * precision. + */ + calculateDepositFee(amountToDeposit: bigint): Promise + /** * @returns Minimum deposit amount. */ diff --git a/sdk/src/lib/contracts/stbtc.ts b/sdk/src/lib/contracts/stbtc.ts index 5eac12c4f..b94b71a34 100644 --- a/sdk/src/lib/contracts/stbtc.ts +++ b/sdk/src/lib/contracts/stbtc.ts @@ -12,4 +12,12 @@ export interface StBTC { * @returns Maximum withdraw value. */ assetsBalanceOf(identifier: ChainIdentifier): Promise + + /** + * Calculates the deposit fee taken from each tBTC deposit to the stBTC pool + * which is then transferred to the treasury. + * @param amount Amount to deposit in 1e18 precision. + * @returns Deposit fee. + */ + calculateDepositFee(amount: bigint): Promise } diff --git a/sdk/src/lib/ethereum/bitcoin-depositor.ts b/sdk/src/lib/ethereum/bitcoin-depositor.ts index 9680c818c..52f634c24 100644 --- a/sdk/src/lib/ethereum/bitcoin-depositor.ts +++ b/sdk/src/lib/ethereum/bitcoin-depositor.ts @@ -9,12 +9,14 @@ import { isAddress, solidityPacked, zeroPadBytes, + Contract, } from "ethers" import { ChainIdentifier, DecodedExtraData, BitcoinDepositor, DepositReceipt, + DepositFees, } from "../contracts" import { BitcoinRawTxVectors } from "../bitcoin" import { EthereumAddress } from "./address" @@ -23,9 +25,23 @@ import { EthersContractDeployment, EthersContractWrapper, } from "./contract" -import { Hex } from "../utils" +import { Hex, fromSatoshi } from "../utils" import { EthereumNetwork } from "./network" +type TbtcDepositParameters = { + depositTreasuryFeeDivisor: bigint + depositTxMaxFee: bigint +} + +type TbtcBridgeMintingParameters = TbtcDepositParameters & { + optimisticMintingFeeDivisor: bigint +} + +type BitcoinDepositorCache = { + tbtcBridgeMintingParameters: TbtcBridgeMintingParameters | undefined + depositorFeeDivisor: bigint | undefined +} + /** * Ethereum implementation of the BitcoinDepositor. */ @@ -36,6 +52,8 @@ class EthereumBitcoinDepositor extends EthersContractWrapper implements BitcoinDepositor { + #cache: BitcoinDepositorCache + constructor(config: EthersContractConfig, network: EthereumNetwork) { let artifact: EthersContractDeployment @@ -49,6 +67,10 @@ class EthereumBitcoinDepositor } super(config, artifact) + this.#cache = { + tbtcBridgeMintingParameters: undefined, + depositorFeeDivisor: undefined, + } } /** @@ -138,6 +160,83 @@ class EthereumBitcoinDepositor async minDepositAmount(): Promise { return this.instance.minDepositAmount() } + + /** + * @see {BitcoinDepositor#calculateDepositFee} + */ + async calculateDepositFee(amountToDeposit: bigint): Promise { + const { + depositTreasuryFeeDivisor, + depositTxMaxFee, + optimisticMintingFeeDivisor, + } = await this.#getTbtcBridgeMintingParameters() + + const treasuryFee = + depositTreasuryFeeDivisor > 0 + ? amountToDeposit / depositTreasuryFeeDivisor + : 0n + + const amountSubTreasury = amountToDeposit - treasuryFee + + const optimisticMintingFee = + optimisticMintingFeeDivisor > 0 + ? amountSubTreasury / optimisticMintingFeeDivisor + : 0n + + const depositorFeeDivisor = await this.#depositorFeeDivisor() + // Compute depositor fee. The fee is calculated based on the initial funding + // transaction amount, before the tBTC protocol network fees were taken. + const depositorFee = + depositorFeeDivisor > 0n ? amountToDeposit / depositorFeeDivisor : 0n + + return { + tbtc: { + treasuryFee, + optimisticMintingFee, + depositTxMaxFee: fromSatoshi(depositTxMaxFee), + }, + acre: { + bitcoinDepositorFee: depositorFee, + }, + } + } + + // TODO: Consider exposing it from tBTC SDK. + async #getTbtcBridgeMintingParameters(): Promise { + if (this.#cache.tbtcBridgeMintingParameters) { + return this.#cache.tbtcBridgeMintingParameters + } + + const bridgeAddress = await this.instance.bridge() + const bridge = new Contract(bridgeAddress, [ + "function depositsParameters()", + ]) + const depositsParameters = + (await bridge.depositsParameters()) as TbtcDepositParameters + + const vaultAddress = await this.getTbtcVaultChainIdentifier() + const vault = new Contract(`0x${vaultAddress.identifierHex}`, [ + "function optimisticMintingFeeDivisor()", + ]) + const optimisticMintingFeeDivisor = + (await vault.optimisticMintingFeeDivisor()) as bigint + + this.#cache.tbtcBridgeMintingParameters = { + ...depositsParameters, + optimisticMintingFeeDivisor, + } + return this.#cache.tbtcBridgeMintingParameters + } + + async #depositorFeeDivisor(): Promise { + if (this.#cache.depositorFeeDivisor) { + return this.#cache.depositorFeeDivisor + } + + this.#cache.depositorFeeDivisor = await this.instance.depositorFeeDivisor() + + return this.#cache.depositorFeeDivisor + } } export { EthereumBitcoinDepositor, packRevealDepositParameters } diff --git a/sdk/src/lib/ethereum/stbtc.ts b/sdk/src/lib/ethereum/stbtc.ts index d4d44610c..e1304529e 100644 --- a/sdk/src/lib/ethereum/stbtc.ts +++ b/sdk/src/lib/ethereum/stbtc.ts @@ -16,6 +16,12 @@ class EthereumStBTC extends EthersContractWrapper implements StBTC { + readonly #BASIS_POINT_SCALE = BigInt(1e4) + + #cache: { + entryFeeBasisPoints?: bigint + } = { entryFeeBasisPoints: undefined } + constructor(config: EthersContractConfig, network: EthereumNetwork) { let artifact: EthersContractDeployment @@ -44,6 +50,28 @@ class EthereumStBTC assetsBalanceOf(identifier: ChainIdentifier): Promise { return this.instance.assetsBalanceOf(`0x${identifier.identifierHex}`) } + + /** + * @see {StBTC#calculateDepositFee} + */ + async calculateDepositFee(amount: bigint): Promise { + const entryFeeBasisPoints = await this.#getEntryFeeBasisPoints() + + return ( + (amount * entryFeeBasisPoints) / + (entryFeeBasisPoints + this.#BASIS_POINT_SCALE) + ) + } + + async #getEntryFeeBasisPoints(): Promise { + if (this.#cache.entryFeeBasisPoints) { + return this.#cache.entryFeeBasisPoints + } + + this.#cache.entryFeeBasisPoints = await this.instance.entryFeeBasisPoints() + + return this.#cache.entryFeeBasisPoints + } } // eslint-disable-next-line import/prefer-default-export diff --git a/sdk/src/modules/staking/index.ts b/sdk/src/modules/staking/index.ts index bf6a69a93..32e8b5363 100644 --- a/sdk/src/modules/staking/index.ts +++ b/sdk/src/modules/staking/index.ts @@ -1,8 +1,17 @@ import { ChainIdentifier, TBTC } from "@keep-network/tbtc-v2.ts" -import { AcreContracts, DepositorProxy } from "../../lib/contracts" +import { AcreContracts, DepositorProxy, DepositFees } from "../../lib/contracts" import { ChainEIP712Signer } from "../../lib/eip712-signer" import { StakeInitialization } from "./stake-initialization" -import { toSatoshi } from "../../lib/utils" +import { fromSatoshi, toSatoshi } from "../../lib/utils" + +/** + * Represents all total deposit fees grouped by network. + */ +export type DepositFee = { + tbtc: bigint + acre: bigint + total: bigint +} /** * Module exposing features related to the staking. @@ -80,6 +89,40 @@ class StakingModule { return this.#contracts.stBTC.assetsBalanceOf(identifier) } + /** + * Estimates the deposit fee based on the provided amount. + * @param amount Amount to deposit in satoshi. + * @returns Deposit fee grouped by tBTC and Acre networks in 1e8 satoshi + * precision and total deposit fee value. + */ + async estimateDepositFee(amount: bigint): Promise { + const amountInTokenPrecision = fromSatoshi(amount) + + const { acre: acreFees, tbtc: tbtcFees } = + await this.#contracts.bitcoinDepositor.calculateDepositFee( + amountInTokenPrecision, + ) + const depositFee = await this.#contracts.stBTC.calculateDepositFee( + amountInTokenPrecision, + ) + + const sumFeesByProtocol = < + T extends DepositFees["tbtc"] | DepositFees["acre"], + >( + fees: T, + ) => Object.values(fees).reduce((reducer, fee) => reducer + fee, 0n) + + const tbtc = toSatoshi(sumFeesByProtocol(tbtcFees)) + + const acre = toSatoshi(sumFeesByProtocol(acreFees)) + toSatoshi(depositFee) + + return { + tbtc, + acre, + total: tbtc + acre, + } + } + /** * @returns Minimum deposit amount in 1e8 satoshi precision. */ diff --git a/sdk/test/lib/ethereum/stbtc.test.ts b/sdk/test/lib/ethereum/stbtc.test.ts index 4d6fa531d..08c7dddc0 100644 --- a/sdk/test/lib/ethereum/stbtc.test.ts +++ b/sdk/test/lib/ethereum/stbtc.test.ts @@ -14,6 +14,7 @@ describe("stbtc", () => { const mockedContractInstance = { balanceOf: jest.fn(), assetsBalanceOf: jest.fn(), + entryFeeBasisPoints: jest.fn(), } beforeAll(() => { @@ -70,4 +71,54 @@ describe("stbtc", () => { expect(result).toEqual(expectedResult) }) }) + + describe("depositFee", () => { + // 0.1 in 1e18 precision + const amount = 100000000000000000n + const mockedEntryFeeBasisPointsValue = 1n + // (amount * basisPoints) / (basisPoints / 1e4) + const expectedResult = 9999000099990n + + let result: bigint + + describe("when the entry fee basis points value is not yet cached", () => { + beforeAll(async () => { + mockedContractInstance.entryFeeBasisPoints.mockResolvedValue( + mockedEntryFeeBasisPointsValue, + ) + + result = await stbtc.calculateDepositFee(amount) + }) + + it("should get the entry fee basis points from contract", () => { + expect(mockedContractInstance.entryFeeBasisPoints).toHaveBeenCalled() + }) + + it("should calculate the deposit fee correctly", () => { + expect(result).toEqual(expectedResult) + }) + }) + + describe("the entry fee basis points value is cached", () => { + beforeAll(async () => { + mockedContractInstance.entryFeeBasisPoints.mockResolvedValue( + mockedEntryFeeBasisPointsValue, + ) + + await stbtc.calculateDepositFee(amount) + + result = await stbtc.calculateDepositFee(amount) + }) + + it("should get the entry fee basis points from cache", () => { + expect( + mockedContractInstance.entryFeeBasisPoints, + ).toHaveBeenCalledTimes(1) + }) + + it("should calculate the deposit fee correctly", () => { + expect(result).toEqual(expectedResult) + }) + }) + }) }) diff --git a/sdk/test/lib/ethereum/tbtc-depositor.test.ts b/sdk/test/lib/ethereum/tbtc-depositor.test.ts index fed57e00a..882ea534a 100644 --- a/sdk/test/lib/ethereum/tbtc-depositor.test.ts +++ b/sdk/test/lib/ethereum/tbtc-depositor.test.ts @@ -1,9 +1,10 @@ -import ethers, { Contract, ZeroAddress } from "ethers" +import ethers, { Contract, ZeroAddress, getAddress } from "ethers" import { EthereumBitcoinDepositor, EthereumAddress, Hex, EthereumSigner, + DepositFees, } from "../../../src" import { extraDataValidTestData } from "./data" @@ -12,28 +13,47 @@ jest.mock("ethers", (): object => ({ ...jest.requireActual("ethers"), })) +const testData = { + depositorFeeDivisor: 1000n, + depositParameters: { + depositTreasuryFeeDivisor: 2_000n, // 1/2000 == 5bps == 0.05% == 0.0005 + depositTxMaxFee: 100_000n, // 100000 satoshi = 0.001 BTC + }, + optimisticMintingFeeDivisor: 500n, // 1/500 = 0.002 = 0.2% +} + describe("BitcoinDepositor", () => { const spyOnEthersDataSlice = jest.spyOn(ethers, "dataSlice") + const spyOnEthersContract = jest.spyOn(ethers, "Contract") const vaultAddress = EthereumAddress.from( ethers.Wallet.createRandom().address, ) + const bridgeAddress = EthereumAddress.from( + ethers.Wallet.createRandom().address, + ) + const minDepositAmount = BigInt(0.015 * 1e18) const mockedContractInstance = { - tbtcVault: jest.fn().mockImplementation(() => vaultAddress.identifierHex), + tbtcVault: jest + .fn() + .mockImplementation(() => `0x${vaultAddress.identifierHex}`), initializeDeposit: jest.fn(), + bridge: jest.fn().mockResolvedValue(`0x${bridgeAddress.identifierHex}`), + depositorFeeDivisor: jest + .fn() + .mockResolvedValue(testData.depositorFeeDivisor), minDepositAmount: jest.fn().mockImplementation(() => minDepositAmount), } + let depositor: EthereumBitcoinDepositor let depositorAddress: EthereumAddress - beforeEach(async () => { - jest - .spyOn(ethers, "Contract") - .mockImplementationOnce( - () => mockedContractInstance as unknown as Contract, - ) + beforeAll(async () => { + spyOnEthersContract.mockImplementationOnce( + () => mockedContractInstance as unknown as Contract, + ) // TODO: get the address from artifact imported from `solidity` package. depositorAddress = EthereumAddress.from( @@ -248,6 +268,151 @@ describe("BitcoinDepositor", () => { ) }) + describe("estimateDepositFees", () => { + const mockedBridgeContractInstance = { + depositsParameters: jest + .fn() + .mockResolvedValue(testData.depositParameters), + } + + const mockedVaultContractInstance = { + optimisticMintingFeeDivisor: jest + .fn() + .mockResolvedValue(testData.optimisticMintingFeeDivisor), + } + + const amountToStake = 100000000000000000n // 0.1 in 1e18 token precision + + const expectedResult = { + tbtc: { + // The fee is calculated based on the initial funding + // transaction amount. `amountToStake / depositTreasuryFeeDivisor` + // 0.00005 tBTC in 1e18 precision. + treasuryFee: 50000000000000n, + // Maximum amount of BTC transaction fee that can + // be incurred by each swept deposit being part of the given sweep + // transaction. + // 0.001 tBTC in 1e18 precision. + depositTxMaxFee: 1000000000000000n, + // The optimistic fee is a percentage AFTER + // the treasury fee is cut: + // `fee = (depositAmount - treasuryFee) / optimisticMintingFeeDivisor` + // 0.0001999 tBTC in 1e18 precision. + optimisticMintingFee: 199900000000000n, + }, + acre: { + // Divisor used to compute the depositor fee taken from each deposit + // and transferred to the treasury upon stake request finalization. + // `depositorFee = depositedAmount / depositorFeeDivisor` + // 0.0001 tBTC in 1e18 precision. + bitcoinDepositorFee: 100000000000000n, + }, + } + + beforeAll(() => { + spyOnEthersContract.mockClear() + + spyOnEthersContract.mockImplementation((target: string) => { + if (getAddress(target) === getAddress(bridgeAddress.identifierHex)) + return mockedBridgeContractInstance as unknown as Contract + if (getAddress(target) === getAddress(vaultAddress.identifierHex)) + return mockedVaultContractInstance as unknown as Contract + + throw new Error("Cannot create mocked contract instance") + }) + }) + + describe("when network fees are not yet cached", () => { + let result: DepositFees + + beforeAll(async () => { + result = await depositor.calculateDepositFee(amountToStake) + }) + + it("should get the bridge contract address", () => { + expect(mockedContractInstance.bridge).toHaveBeenCalled() + }) + + it("should create the ethers Contract instance of the Bridge contract", () => { + expect(Contract).toHaveBeenNthCalledWith( + 1, + `0x${bridgeAddress.identifierHex}`, + ["function depositsParameters()"], + ) + }) + + it("should get the deposit parameters from chain", () => { + expect( + mockedBridgeContractInstance.depositsParameters, + ).toHaveBeenCalled() + }) + + it("should get the vault contract address", () => { + expect(mockedContractInstance.tbtcVault).toHaveBeenCalled() + }) + + it("should create the ethers Contract instance of the Bridge contract", () => { + expect(Contract).toHaveBeenNthCalledWith( + 2, + `0x${vaultAddress.identifierHex}`, + ["function optimisticMintingFeeDivisor()"], + ) + }) + + it("should get the optimistic minting fee divisor", () => { + expect( + mockedVaultContractInstance.optimisticMintingFeeDivisor, + ).toHaveBeenCalled() + }) + + it("should get the depositor fee divisor", () => { + expect(mockedContractInstance.depositorFeeDivisor).toHaveBeenCalled() + }) + + it("should return correct fees", () => { + expect(result).toMatchObject(expectedResult) + }) + }) + + describe("when network fees are already cached", () => { + let result2: DepositFees + + beforeAll(async () => { + mockedContractInstance.bridge.mockClear() + mockedContractInstance.tbtcVault.mockClear() + mockedContractInstance.depositorFeeDivisor.mockClear() + mockedBridgeContractInstance.depositsParameters.mockClear() + mockedVaultContractInstance.optimisticMintingFeeDivisor.mockClear() + + result2 = await depositor.calculateDepositFee(amountToStake) + }) + + it("should get the deposit parameters from cache", () => { + expect(mockedContractInstance.bridge).toHaveBeenCalledTimes(0) + expect( + mockedBridgeContractInstance.depositsParameters, + ).toHaveBeenCalledTimes(0) + }) + + it("should get the optimistic minting fee divisor from cache", () => { + expect(mockedContractInstance.tbtcVault).toHaveBeenCalledTimes(0) + expect( + mockedVaultContractInstance.optimisticMintingFeeDivisor, + ).toHaveBeenCalledTimes(0) + }) + + it("should get the bitcoin depositor fee divisor from cache", () => { + expect( + mockedContractInstance.depositorFeeDivisor, + ).toHaveBeenCalledTimes(0) + }) + + it("should return correct fees", () => { + expect(result2).toMatchObject(expectedResult) + }) + }) + }) + describe("minDepositAmount", () => { it("should return minimum deposit amount", async () => { const result = await depositor.minDepositAmount() diff --git a/sdk/test/modules/staking.test.ts b/sdk/test/modules/staking.test.ts index e8a91b214..81909295e 100644 --- a/sdk/test/modules/staking.test.ts +++ b/sdk/test/modules/staking.test.ts @@ -8,11 +8,13 @@ import { DepositorProxy, DepositReceipt, EthereumAddress, + DepositFees, + DepositFee, } from "../../src" +import * as satoshiConverter from "../../src/lib/utils/satoshi-converter" import { MockAcreContracts } from "../utils/mock-acre-contracts" import { MockMessageSigner } from "../utils/mock-message-signer" import { MockTBTC } from "../utils/mock-tbtc" -import * as satoshiConverterUtils from "../../src/lib/utils/satoshi-converter" const stakingModuleData: { initializeStake: { @@ -22,6 +24,13 @@ const stakingModuleData: { bitcoinRecoveryAddress: string mockedDepositBTCAddress: string } + estimateDepositFees: { + amount: bigint + amountIn1e18: bigint + mockedDepositFees: DepositFees + stBTCDepositFee: bigint + expectedDepositFeesInSatoshi: DepositFee + } } = { initializeStake: { staker: EthereumAddress.from(ethers.Wallet.createRandom().address), @@ -33,6 +42,32 @@ const stakingModuleData: { mockedDepositBTCAddress: "tb1qma629cu92skg0t86lftyaf9uflzwhp7jk63h6mpmv3ezh6puvdhs6w2r05", }, + estimateDepositFees: { + amount: 10_000_000n, // 0.1 BTC, + // 0.1 tBTC in 1e18 precision. + amountIn1e18: 100000000000000000n, + mockedDepositFees: { + tbtc: { + // 0.00005 tBTC in 1e18 precision. + treasuryFee: 50000000000000n, + // 0.001 tBTC in 1e18 precision. + depositTxMaxFee: 1000000000000000n, + // 0.0001999 tBTC in 1e18 precision. + optimisticMintingFee: 199900000000000n, + }, + acre: { + // 0.0001 tBTC in 1e18 precision. + bitcoinDepositorFee: 100000000000000n, + }, + }, + // 0.001 in 1e18 precison + stBTCDepositFee: 1000000000000000n, + expectedDepositFeesInSatoshi: { + tbtc: 124990n, + acre: 110000n, + total: 234990n, + }, + }, } const stakingInitializationData: { @@ -397,9 +432,75 @@ describe("Staking", () => { }) }) + describe("estimateDepositFees", () => { + const { + estimateDepositFees: { + amount, + amountIn1e18, + mockedDepositFees, + expectedDepositFeesInSatoshi, + stBTCDepositFee, + }, + } = stakingModuleData + + let result: DepositFee + const spyOnToSatoshi = jest.spyOn(satoshiConverter, "toSatoshi") + const spyOnFromSatoshi = jest.spyOn(satoshiConverter, "fromSatoshi") + + beforeAll(async () => { + contracts.bitcoinDepositor.calculateDepositFee = jest + .fn() + .mockResolvedValue(mockedDepositFees) + + contracts.stBTC.calculateDepositFee = jest + .fn() + .mockResolvedValue(stBTCDepositFee) + + result = await staking.estimateDepositFee(amount) + }) + + it("should convert provided amount from satoshi to token precision", () => { + expect(spyOnFromSatoshi).toHaveBeenNthCalledWith(1, amount) + }) + + it("should get the deposit fees from Acre Bitcoin Depositor contract handle", () => { + expect( + contracts.bitcoinDepositor.calculateDepositFee, + ).toHaveBeenCalledWith(amountIn1e18) + }) + + it("should get the stBTC deposit fee", () => { + expect(contracts.stBTC.calculateDepositFee).toHaveBeenCalledWith( + amountIn1e18, + ) + }) + + it("should convert tBTC network fees to satoshi", () => { + const { + tbtc: { depositTxMaxFee, treasuryFee, optimisticMintingFee }, + } = mockedDepositFees + const totalTbtcFees = depositTxMaxFee + treasuryFee + optimisticMintingFee + + expect(spyOnToSatoshi).toHaveBeenNthCalledWith(1, totalTbtcFees) + }) + + it("should convert Acre network fees to satoshi", () => { + const { + acre: { bitcoinDepositorFee }, + } = mockedDepositFees + const totalAcreFees = bitcoinDepositorFee + + expect(spyOnToSatoshi).toHaveBeenNthCalledWith(2, totalAcreFees) + }) + + it("should return the deposit fees in satoshi precision", () => { + expect(result).toMatchObject(expectedDepositFeesInSatoshi) + }) + }) + describe("minDepositAmount", () => { describe("should return minimum deposit amount", () => { - const spyOnToSatoshi = jest.spyOn(satoshiConverterUtils, "toSatoshi") + const spyOnToSatoshi = jest.spyOn(satoshiConverter, "toSatoshi") const mockedResult = BigInt(0.015 * 1e18) // The returned result should be in satoshi precision const expectedResult = BigInt(0.015 * 1e8) diff --git a/sdk/test/utils/mock-acre-contracts.ts b/sdk/test/utils/mock-acre-contracts.ts index 6cdc670c3..9a111cffc 100644 --- a/sdk/test/utils/mock-acre-contracts.ts +++ b/sdk/test/utils/mock-acre-contracts.ts @@ -13,12 +13,14 @@ export class MockAcreContracts implements AcreContracts { decodeExtraData: jest.fn(), encodeExtraData: jest.fn(), revealDeposit: jest.fn(), + calculateDepositFee: jest.fn(), minDepositAmount: jest.fn(), } as BitcoinDepositor this.stBTC = { balanceOf: jest.fn(), assetsBalanceOf: jest.fn(), + calculateDepositFee: jest.fn(), } as StBTC } }