ERC4626Fees.sol 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.0;
  3. import "../../token/ERC20/extensions/ERC4626.sol";
  4. abstract contract ERC4626Fees is ERC4626 {
  5. using Math for uint256;
  6. /** @dev See {IERC4626-previewDeposit}. */
  7. function previewDeposit(uint256 assets) public view virtual override returns (uint256) {
  8. uint256 fee = _feeOnTotal(assets, _entryFeeBasePoint());
  9. return super.previewDeposit(assets - fee);
  10. }
  11. /** @dev See {IERC4626-previewMint}. */
  12. function previewMint(uint256 shares) public view virtual override returns (uint256) {
  13. uint256 assets = super.previewMint(shares);
  14. return assets + _feeOnRaw(assets, _entryFeeBasePoint());
  15. }
  16. /** @dev See {IERC4626-previewWithdraw}. */
  17. function previewWithdraw(uint256 assets) public view virtual override returns (uint256) {
  18. uint256 fee = _feeOnRaw(assets, _exitFeeBasePoint());
  19. return super.previewWithdraw(assets + fee);
  20. }
  21. /** @dev See {IERC4626-previewRedeem}. */
  22. function previewRedeem(uint256 shares) public view virtual override returns (uint256) {
  23. uint256 assets = super.previewRedeem(shares);
  24. return assets - _feeOnTotal(assets, _exitFeeBasePoint());
  25. }
  26. /** @dev See {IERC4626-_deposit}. */
  27. function _deposit(address caller, address receiver, uint256 assets, uint256 shares) internal virtual override {
  28. uint256 fee = _feeOnTotal(assets, _entryFeeBasePoint());
  29. address recipient = _entryFeeRecipient();
  30. super._deposit(caller, receiver, assets, shares);
  31. if (fee > 0 && recipient != address(this)) {
  32. SafeERC20.safeTransfer(IERC20(asset()), recipient, fee);
  33. }
  34. }
  35. /** @dev See {IERC4626-_deposit}. */
  36. function _withdraw(
  37. address caller,
  38. address receiver,
  39. address owner,
  40. uint256 assets,
  41. uint256 shares
  42. ) internal virtual override {
  43. uint256 fee = _feeOnRaw(assets, _exitFeeBasePoint());
  44. address recipient = _exitFeeRecipient();
  45. super._withdraw(caller, receiver, owner, assets, shares);
  46. if (fee > 0 && recipient != address(this)) {
  47. SafeERC20.safeTransfer(IERC20(asset()), recipient, fee);
  48. }
  49. }
  50. function _entryFeeBasePoint() internal view virtual returns (uint256) {
  51. return 0;
  52. }
  53. function _entryFeeRecipient() internal view virtual returns (address) {
  54. return address(0);
  55. }
  56. function _exitFeeBasePoint() internal view virtual returns (uint256) {
  57. return 0;
  58. }
  59. function _exitFeeRecipient() internal view virtual returns (address) {
  60. return address(0);
  61. }
  62. function _feeOnRaw(uint256 assets, uint256 feeBasePoint) private pure returns (uint256) {
  63. return assets.mulDiv(feeBasePoint, 1e5, Math.Rounding.Up);
  64. }
  65. function _feeOnTotal(uint256 assets, uint256 feeBasePoint) private pure returns (uint256) {
  66. return assets.mulDiv(feeBasePoint, feeBasePoint + 1e5, Math.Rounding.Up);
  67. }
  68. }