@@ -82,49 +82,27 @@ contract ZeniEngine is ReentrancyGuard {
8282 require (success, ZeniEngine__TokenTransferFailed ());
8383 }
8484
85- /// @param collateral The address of the collateral token.
86- /// @param collateralAmount The amount of the collateral to deposit.
87- /// @param amountZeniToMint The amount of Zeni to mint.
88- /// @notice Deposits your collateral and mints Zeni in one transaction.
89- function depositCollateralAndMintZeni (
90- address collateral ,
91- uint256 collateralAmount ,
92- uint256 amountZeniToMint
93- ) external {
94- depositCollateral (collateral, collateralAmount);
95- mintZeni (amountZeniToMint);
96- }
97-
9885 /// @param collateral The address of the collateral token.
9986 /// @param amount The amount of the collateral to redeem.
10087 function redeemCollateral (address collateral , uint256 amount ) public nonReentrant amountGreaterThanZero (amount) {
10188 _redeemCollateral (msg .sender , msg .sender , collateral, amount);
102- uint256 healthFactor = _getHealthFactor (msg .sender );
89+ uint256 healthFactor = getHealthFactor (msg .sender );
10390 require (healthFactor >= MINIMUM_HEALTH_FACTOR, ZeniEngine__HealthFactorBelowMinimumThreshold ());
10491 }
10592
106- /// @param collateral The address of the collateral token.
107- /// @param collateralAmount The amount of the collateral to redeem.
108- /// @param amountZeniToBurn The amount of Zeni to burn.
109- /// @notice Burns Zeni and redeems the underlying collateral in one transaction.
110- function redeemCollateralForZeni (address collateral , uint256 collateralAmount , uint256 amountZeniToBurn ) external {
111- burnZeni (amountZeniToBurn);
112- redeemCollateral (collateral, collateralAmount);
113- }
114-
11593 /// @param amount The amount of Zeni to mint.
11694 function mintZeni (uint256 amount ) public nonReentrant amountGreaterThanZero (amount) {
11795 address user = msg .sender ;
11896 s_amountMinted[user] += amount;
119- uint256 healthFactor = _getHealthFactor (user);
97+ uint256 healthFactor = getHealthFactor (user);
12098 require (healthFactor >= MINIMUM_HEALTH_FACTOR, ZeniEngine__HealthFactorBelowMinimumThreshold ());
12199 bool success = i_zeni.mint (user, amount);
122100 require (success, ZeniEngine__MintFailed ());
123101 emit ZeniMinted (user, amount);
124102 }
125103
126104 function burnZeni (uint256 amount ) public amountGreaterThanZero (amount) {
127- _burnZeni (msg .sender , msg .sender , amount);
105+ _burnZeni (msg .sender , msg .sender , amount);
128106 }
129107
130108 function getTokenAmountFromUSD (
@@ -135,6 +113,58 @@ contract ZeniEngine is ReentrancyGuard {
135113 return (amountZeniToBurn * DECIMALS) / (uint256 (price) * PRICE_FEED_PRECISION_TO_MATCH_DECIMALS_PRECISION);
136114 }
137115
116+ function getHealthFactor (address user ) public view returns (uint256 healthFactor ) {
117+ uint256 amountMinted = s_amountMinted[user];
118+ uint256 collateralValueInUSD = getAccountCollateralValueInUSD (user);
119+ uint256 collateralValueAdjustedForThreshold = (collateralValueInUSD * LIQUIDATION_THRESHOLD_IN_PERCENT) /
120+ LIQUIDATION_PRECISION;
121+ if (amountMinted != 0 ) {
122+ return (collateralValueAdjustedForThreshold * DECIMALS) / amountMinted;
123+ }
124+ return type (uint256 ).max;
125+ }
126+
127+ function getAccountCollateralValueInUSD (address user ) public view returns (uint256 accountCollateralValueInUSD ) {
128+ uint256 length = s_supportedCollaterals.length ;
129+ for (uint8 i; i < length; ) {
130+ address collateral = s_supportedCollaterals[i];
131+ uint256 amount = s_collateralBalance[user][collateral];
132+ accountCollateralValueInUSD += getCollateralValueInUSD (collateral, amount);
133+
134+ unchecked {
135+ ++ i;
136+ }
137+ }
138+ return accountCollateralValueInUSD;
139+ }
140+
141+ function getCollateralValueInUSD (address token , uint256 amount ) public view returns (uint256 collateralValueInUSD ) {
142+ (, int256 price , , , ) = AggregatorV3Interface (s_priceFeeds[token]).latestRoundData ();
143+ return (amount * (uint256 (price) * PRICE_FEED_PRECISION_TO_MATCH_DECIMALS_PRECISION)) / DECIMALS;
144+ }
145+
146+ /// @param collateral The address of the collateral token.
147+ /// @param collateralAmount The amount of the collateral to deposit.
148+ /// @param amountZeniToMint The amount of Zeni to mint.
149+ /// @notice Deposits your collateral and mints Zeni in one transaction.
150+ function depositCollateralAndMintZeni (
151+ address collateral ,
152+ uint256 collateralAmount ,
153+ uint256 amountZeniToMint
154+ ) external {
155+ depositCollateral (collateral, collateralAmount);
156+ mintZeni (amountZeniToMint);
157+ }
158+
159+ /// @param collateral The address of the collateral token.
160+ /// @param collateralAmount The amount of the collateral to redeem.
161+ /// @param amountZeniToBurn The amount of Zeni to burn.
162+ /// @notice Burns Zeni and redeems the underlying collateral in one transaction.
163+ function redeemCollateralForZeni (address collateral , uint256 collateralAmount , uint256 amountZeniToBurn ) external {
164+ burnZeni (amountZeniToBurn);
165+ redeemCollateral (collateral, collateralAmount);
166+ }
167+
138168 /// @param user The address of the user to be liquidated, whose health factor is below MINIMUM_HEALTH_FACTOR.
139169 /// @param collateral The address of the collateral token.
140170 /// @param amountZeniToBurn The amount of Zeni to burn to improve the user's health factor.
@@ -144,7 +174,7 @@ contract ZeniEngine is ReentrancyGuard {
144174 address collateral ,
145175 uint256 amountZeniToBurn
146176 ) external nonReentrant amountGreaterThanZero (amountZeniToBurn) {
147- uint256 startingHealthFactor = _getHealthFactor (user);
177+ uint256 startingHealthFactor = getHealthFactor (user);
148178 require (
149179 startingHealthFactor < MINIMUM_HEALTH_FACTOR,
150180 ZeniEngine__HealthFactorIsGreaterThanMinimumHealthFactor ()
@@ -155,25 +185,13 @@ contract ZeniEngine is ReentrancyGuard {
155185 uint256 totalCollateralToRedeem = tokenAmountCoveredFromDebt + bonusCollateral;
156186 _redeemCollateral (user, msg .sender , collateral, totalCollateralToRedeem);
157187 _burnZeni (user, msg .sender , amountZeniToBurn);
158- uint256 endingHealthFactor = _getHealthFactor (user);
188+ uint256 endingHealthFactor = getHealthFactor (user);
159189 require (endingHealthFactor >= startingHealthFactor, ZeniEngine__HealthFactorNotImproved ());
160- uint256 liquidatorHealthFactor = _getHealthFactor (msg .sender );
161- require (liquidatorHealthFactor >= MINIMUM_HEALTH_FACTOR, ZeniEngine__LiquidatorHealthFactorBelowMinimumThreshold ());
162- }
163-
164- function getHealthFactor (address user ) external view returns (uint256 healthFactor ) {
165- return _getHealthFactor (user);
166- }
167-
168- function getAccountCollateralValueInUSD (address user ) external view returns (uint256 collateralValueInUSD ) {
169- return _getAccountCollateralValueInUSD (user);
170- }
171-
172- function getCollateralValueInUSD (
173- address token ,
174- uint256 amount
175- ) external view returns (uint256 collateralValueInUSD ) {
176- return _getCollateralValueInUSD (token, amount);
190+ uint256 liquidatorHealthFactor = getHealthFactor (msg .sender );
191+ require (
192+ liquidatorHealthFactor >= MINIMUM_HEALTH_FACTOR,
193+ ZeniEngine__LiquidatorHealthFactorBelowMinimumThreshold ()
194+ );
177195 }
178196
179197 function getSupportedCollaterals () external view returns (address [] memory supportedCollaterals ) {
@@ -205,37 +223,4 @@ contract ZeniEngine is ReentrancyGuard {
205223 i_zeni.burn (amount);
206224 emit ZeniBurned (from, amount);
207225 }
208-
209- function _getHealthFactor (address user ) private view returns (uint256 healthFactor ) {
210- uint256 amountMinted = s_amountMinted[user];
211- uint256 collateralValueInUSD = _getAccountCollateralValueInUSD (user);
212- uint256 collateralValueAdjustedForThreshold = (collateralValueInUSD * LIQUIDATION_THRESHOLD_IN_PERCENT) /
213- LIQUIDATION_PRECISION;
214- if (amountMinted != 0 ) {
215- return (collateralValueAdjustedForThreshold * DECIMALS) / amountMinted;
216- }
217- return type (uint256 ).max;
218- }
219-
220- function _getAccountCollateralValueInUSD (address user ) private view returns (uint256 accountCollateralValueInUSD ) {
221- uint256 length = s_supportedCollaterals.length ;
222- for (uint8 i; i < length; ) {
223- address collateral = s_supportedCollaterals[i];
224- uint256 amount = s_collateralBalance[user][collateral];
225- accountCollateralValueInUSD += _getCollateralValueInUSD (collateral, amount);
226-
227- unchecked {
228- ++ i;
229- }
230- }
231- return accountCollateralValueInUSD;
232- }
233-
234- function _getCollateralValueInUSD (
235- address token ,
236- uint256 amount
237- ) private view returns (uint256 collateralValueInUSD ) {
238- (, int256 price , , , ) = AggregatorV3Interface (s_priceFeeds[token]).latestRoundData ();
239- return (amount * (uint256 (price) * PRICE_FEED_PRECISION_TO_MATCH_DECIMALS_PRECISION)) / DECIMALS;
240- }
241226}
0 commit comments