@@ -5,41 +5,46 @@ pragma solidity ^0.8.0;
5
5
import "../../token/ERC20/extensions/ERC4626Upgradeable.sol " ;
6
6
import "../../proxy/utils/Initializable.sol " ;
7
7
8
+ /// @dev ERC4626 vault with entry/exit fees expressed in https://en.wikipedia.org/wiki/Basis_point[basis point (bp)].
8
9
abstract contract ERC4626FeesUpgradeable is Initializable , ERC4626Upgradeable {
9
10
using MathUpgradeable for uint256 ;
10
11
12
+ uint256 private constant _BASIS_POINT_SCALE = 1e4 ;
13
+
11
14
function __ERC4626Fees_init () internal onlyInitializing {
12
15
}
13
16
14
17
function __ERC4626Fees_init_unchained () internal onlyInitializing {
15
18
}
16
- /** @dev See {IERC4626-previewDeposit}. */
19
+ // === Overrides ===
20
+
21
+ /// @dev Preview taking an entry fee on deposit. See {IERC4626-previewDeposit}.
17
22
function previewDeposit (uint256 assets ) public view virtual override returns (uint256 ) {
18
- uint256 fee = _feeOnTotal (assets, _entryFeeBasePoint ());
23
+ uint256 fee = _feeOnTotal (assets, _entryFeeBasisPoints ());
19
24
return super .previewDeposit (assets - fee);
20
25
}
21
26
22
- /** @dev See {IERC4626-previewMint}. */
27
+ /// @dev Preview adding an entry fee on mint. See {IERC4626-previewMint}.
23
28
function previewMint (uint256 shares ) public view virtual override returns (uint256 ) {
24
29
uint256 assets = super .previewMint (shares);
25
- return assets + _feeOnRaw (assets, _entryFeeBasePoint ());
30
+ return assets + _feeOnRaw (assets, _entryFeeBasisPoints ());
26
31
}
27
32
28
- /** @dev See {IERC4626-previewWithdraw}. */
33
+ /// @dev Preview adding an exit fee on withdraw. See {IERC4626-previewWithdraw}.
29
34
function previewWithdraw (uint256 assets ) public view virtual override returns (uint256 ) {
30
- uint256 fee = _feeOnRaw (assets, _exitFeeBasePoint ());
35
+ uint256 fee = _feeOnRaw (assets, _exitFeeBasisPoints ());
31
36
return super .previewWithdraw (assets + fee);
32
37
}
33
38
34
- /** @dev See {IERC4626-previewRedeem}. */
39
+ /// @dev Preview taking an exit fee on redeem. See {IERC4626-previewRedeem}.
35
40
function previewRedeem (uint256 shares ) public view virtual override returns (uint256 ) {
36
41
uint256 assets = super .previewRedeem (shares);
37
- return assets - _feeOnTotal (assets, _exitFeeBasePoint ());
42
+ return assets - _feeOnTotal (assets, _exitFeeBasisPoints ());
38
43
}
39
44
40
- /** @dev See {IERC4626-_deposit}. */
45
+ /// @dev Send entry fee to {_entryFeeRecipient}. See {IERC4626-_deposit}.
41
46
function _deposit (address caller , address receiver , uint256 assets , uint256 shares ) internal virtual override {
42
- uint256 fee = _feeOnTotal (assets, _entryFeeBasePoint ());
47
+ uint256 fee = _feeOnTotal (assets, _entryFeeBasisPoints ());
43
48
address recipient = _entryFeeRecipient ();
44
49
45
50
super ._deposit (caller, receiver, assets, shares);
@@ -49,15 +54,15 @@ abstract contract ERC4626FeesUpgradeable is Initializable, ERC4626Upgradeable {
49
54
}
50
55
}
51
56
52
- /** @dev See {IERC4626-_deposit}. */
57
+ /// @dev Send exit fee to {_exitFeeRecipient}. See {IERC4626-_deposit}.
53
58
function _withdraw (
54
59
address caller ,
55
60
address receiver ,
56
61
address owner ,
57
62
uint256 assets ,
58
63
uint256 shares
59
64
) internal virtual override {
60
- uint256 fee = _feeOnRaw (assets, _exitFeeBasePoint ());
65
+ uint256 fee = _feeOnRaw (assets, _exitFeeBasisPoints ());
61
66
address recipient = _exitFeeRecipient ();
62
67
63
68
super ._withdraw (caller, receiver, owner, assets, shares);
@@ -67,28 +72,36 @@ abstract contract ERC4626FeesUpgradeable is Initializable, ERC4626Upgradeable {
67
72
}
68
73
}
69
74
70
- function _entryFeeBasePoint () internal view virtual returns (uint256 ) {
71
- return 0 ;
75
+ // === Fee configuration ===
76
+
77
+ function _entryFeeBasisPoints () internal view virtual returns (uint256 ) {
78
+ return 0 ; // replace with e.g. 100 for 1%
72
79
}
73
80
74
- function _entryFeeRecipient () internal view virtual returns (address ) {
75
- return address ( 0 );
81
+ function _exitFeeBasisPoints () internal view virtual returns (uint256 ) {
82
+ return 0 ; // replace with e.g. 100 for 1%
76
83
}
77
84
78
- function _exitFeeBasePoint () internal view virtual returns (uint256 ) {
79
- return 0 ;
85
+ function _entryFeeRecipient () internal view virtual returns (address ) {
86
+ return address ( 0 ); // replace with e.g. a treasury address
80
87
}
81
88
82
89
function _exitFeeRecipient () internal view virtual returns (address ) {
83
- return address (0 );
90
+ return address (0 ); // replace with e.g. a treasury address
84
91
}
85
92
86
- function _feeOnRaw (uint256 assets , uint256 feeBasePoint ) private pure returns (uint256 ) {
87
- return assets.mulDiv (feeBasePoint, 1e5 , MathUpgradeable.Rounding.Up);
93
+ // === Fee operations ===
94
+
95
+ /// @dev Calculates the fees that should be added to an amount `assets` that does not already include fees.
96
+ /// Used in {IERC4626-mint} and {IERC4626-withdraw} operations.
97
+ function _feeOnRaw (uint256 assets , uint256 feeBasisPoints ) private pure returns (uint256 ) {
98
+ return assets.mulDiv (feeBasisPoints, _BASIS_POINT_SCALE, MathUpgradeable.Rounding.Up);
88
99
}
89
100
90
- function _feeOnTotal (uint256 assets , uint256 feeBasePoint ) private pure returns (uint256 ) {
91
- return assets.mulDiv (feeBasePoint, feeBasePoint + 1e5 , MathUpgradeable.Rounding.Up);
101
+ /// @dev Calculates the fee part of an amount `assets` that already includes fees.
102
+ /// Used in {IERC4626-deposit} and {IERC4626-redeem} operations.
103
+ function _feeOnTotal (uint256 assets , uint256 feeBasisPoints ) private pure returns (uint256 ) {
104
+ return assets.mulDiv (feeBasisPoints, feeBasisPoints + _BASIS_POINT_SCALE, MathUpgradeable.Rounding.Up);
92
105
}
93
106
94
107
/**
0 commit comments