Skip to content

Commit

Permalink
Merge branch 'main' into bound-fees-upper-limit
Browse files Browse the repository at this point in the history
  • Loading branch information
dimpar authored May 9, 2024
2 parents 328a7ed + 6303018 commit f48e534
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
7 changes: 7 additions & 0 deletions solidity/contracts/lib/ERC4626Fees.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ abstract contract ERC4626Fees is ERC4626Upgradeable {
}
}

/// @dev Calculate the maximum amount of assets that can be withdrawn
/// by an account including fees. See {IERC4626-maxWithdraw}.
function _maxWithdraw(address account) internal view returns (uint256) {
uint256 maxAssets = super.maxWithdraw(account);
return maxAssets - _feeOnTotal(maxAssets, _exitFeeBasisPoints());
}

// === Fee configuration ===

// slither-disable-next-line dead-code
Expand Down
2 changes: 1 addition & 1 deletion solidity/contracts/stBTC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ contract stBTC is ERC4626Fees, PausableOwnable {
if (paused()) {
return 0;
}
return super.maxWithdraw(owner);
return _maxWithdraw(owner);
}

/// @dev Returns the maximum amount of Vault shares that can be redeemed from
Expand Down
44 changes: 44 additions & 0 deletions solidity/test/stBTC.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2172,6 +2172,50 @@ describe("stBTC", () => {
})
})

describe("maxWithdraw", () => {
beforeAfterSnapshotWrapper()
const amountToDeposit = to1e18(1)
let expectedDepositedAmount: bigint
let expectedWithdrawnAmount: bigint

before(async () => {
await tbtc
.connect(depositor1)
.approve(await stbtc.getAddress(), amountToDeposit)
await stbtc
.connect(depositor1)
.deposit(amountToDeposit, depositor1.address)
expectedDepositedAmount =
amountToDeposit - feeOnTotal(amountToDeposit, entryFeeBasisPoints)
expectedWithdrawnAmount =
expectedDepositedAmount -
feeOnTotal(expectedDepositedAmount, exitFeeBasisPoints)
})

it("should account for the exit fee", async () => {
const maxWithdraw = await stbtc.maxWithdraw(depositor1.address)

expect(maxWithdraw).to.be.eq(expectedWithdrawnAmount)
})

it("should be equal to the actual redeemable amount", async () => {
const maxWithdraw = await stbtc.maxWithdraw(depositor1.address)
const availableShares = await stbtc.balanceOf(depositor1.address)

const tx = await stbtc.redeem(
availableShares,
depositor1.address,
depositor1.address,
)

await expect(tx).to.changeTokenBalances(
tbtc,
[depositor1.address],
[maxWithdraw],
)
})
})

describe("feeOnTotal - internal test helper", () => {
context("when the fee's modulo remainder is greater than 0", () => {
it("should add 1 to the result", () => {
Expand Down

0 comments on commit f48e534

Please sign in to comment.