@@ -93,8 +93,11 @@ abstract contract ERC4626 is ERC20, IERC4626 {
93
93
94
94
address caller = _msgSender ();
95
95
uint256 shares = previewDeposit (assets);
96
- _mint (receiver, shares);
96
+
97
+ // if _asset is ERC777, transferFrom can call reenter BEFORE the transfer happens through
98
+ // the tokensToSend hook, so we need to transfer before we mint to keep the invariants.
97
99
SafeERC20.safeTransferFrom (_asset, caller, address (this ), assets);
100
+ _mint (receiver, shares);
98
101
99
102
emit Deposit (caller, receiver, assets, shares);
100
103
@@ -107,8 +110,11 @@ abstract contract ERC4626 is ERC20, IERC4626 {
107
110
108
111
address caller = _msgSender ();
109
112
uint256 assets = previewMint (shares);
110
- _mint (receiver, shares);
113
+
114
+ // if _asset is ERC777, transferFrom can call reenter BEFORE the transfer happens through
115
+ // the tokensToSend hook, so we need to transfer before we mint to keep the invariants.
111
116
SafeERC20.safeTransferFrom (_asset, caller, address (this ), assets);
117
+ _mint (receiver, shares);
112
118
113
119
emit Deposit (caller, receiver, assets, shares);
114
120
@@ -130,6 +136,8 @@ abstract contract ERC4626 is ERC20, IERC4626 {
130
136
_spendAllowance (owner, caller, shares);
131
137
}
132
138
139
+ // if _asset is ERC777, transferFrom can call reenter BEFORE the transfer happens through
140
+ // the tokensReceived hook, so we need to transfer after we burn to keep the invariants.
133
141
_burn (owner, shares);
134
142
SafeERC20.safeTransfer (_asset, receiver, assets);
135
143
@@ -153,6 +161,8 @@ abstract contract ERC4626 is ERC20, IERC4626 {
153
161
_spendAllowance (owner, caller, shares);
154
162
}
155
163
164
+ // if _asset is ERC777, transferFrom can call reenter BEFORE the transfer happens through
165
+ // the tokensReceived hook, so we need to transfer after we burn to keep the invariants.
156
166
_burn (owner, shares);
157
167
SafeERC20.safeTransfer (_asset, receiver, assets);
158
168
0 commit comments