@@ -91,12 +91,30 @@ contract EzETHHyperdriveTest is InstanceTest {
9191 /// @dev Converts base amount to the equivalent about in EzETH.
9292 function convertToShares (
9393 uint256 baseAmount
94- ) internal view override returns (uint256 shareAmount ) {
94+ ) internal view override returns (uint256 ) {
9595 // Get protocol state information used for calculating shares.
9696 (uint256 sharePrice , , ) = getSharePrice ();
9797 return baseAmount.divDown (sharePrice);
9898 }
9999
100+ /// @dev Converts share amount to the equivalent amount in ETH.
101+ function convertToBase (
102+ uint256 baseAmount
103+ ) internal view override returns (uint256 ) {
104+ // Get the total TVL priced in ETH from RestakeManager.
105+ (, , uint256 totalTVL ) = RESTAKE_MANAGER.calculateTVLs ();
106+
107+ // Get the total supply of the ezETH token.
108+ uint256 totalSupply = EZETH.totalSupply ();
109+
110+ return
111+ RENZO_ORACLE.calculateRedeemAmount (
112+ baseAmount,
113+ totalSupply,
114+ totalTVL
115+ );
116+ }
117+
100118 /// @dev Deploys the EzETH deployer coordinator contract.
101119 function deployCoordinator () internal override returns (address ) {
102120 vm.startPrank (alice);
@@ -114,6 +132,88 @@ contract EzETHHyperdriveTest is InstanceTest {
114132 );
115133 }
116134
135+ /// @dev Fetches the token balance information of an account.
136+ function getTokenBalances (
137+ address account
138+ ) internal view override returns (uint256 , uint256 ) {
139+ // EzETH does not have a convenient function for fetching base balance.
140+ return (0 , EZETH.balanceOf (account));
141+ }
142+
143+ /// @dev Fetches the total supply of the base and share tokens.
144+ function getSupply () internal view override returns (uint256 , uint256 ) {
145+ (, uint256 totalPooledEther , ) = getSharePrice ();
146+ return (totalPooledEther, EZETH.totalSupply ());
147+ }
148+
149+ /// @dev Verifies that deposit accounting is correct when opening positions.
150+ function verifyDeposit (
151+ address trader ,
152+ uint256 basePaid ,
153+ bool asBase ,
154+ uint256 totalBaseSupplyBefore ,
155+ uint256 totalSharesBefore ,
156+ AccountBalances memory traderBalancesBefore ,
157+ AccountBalances memory hyperdriveBalancesBefore
158+ ) internal override {
159+ if (asBase) {
160+ // Ensure that the amount of pooled ether increased by the base paid.
161+ (, uint256 totalPooledEther , ) = getSharePrice ();
162+ assertEq (totalPooledEther, totalBaseSupplyBefore + basePaid);
163+
164+ // Ensure that the ETH balances were updated correctly.
165+ assertEq (
166+ address (hyperdrive).balance,
167+ hyperdriveBalancesBefore.ETHBalance
168+ );
169+ assertEq (bob.balance, traderBalancesBefore.ETHBalance - basePaid);
170+
171+ // Ensure ezETH shares were updated correctly.
172+ assertEq (
173+ EZETH.balanceOf (trader),
174+ traderBalancesBefore.sharesBalance
175+ );
176+
177+ // Ensure that the ezETH shares were updated correctly.
178+ uint256 expectedShares = RENZO_ORACLE.calculateMintAmount (
179+ totalBaseSupplyBefore,
180+ basePaid,
181+ totalSharesBefore
182+ );
183+ assertEq (EZETH.totalSupply (), totalSharesBefore + expectedShares);
184+ assertEq (
185+ EZETH.balanceOf (address (hyperdrive)),
186+ hyperdriveBalancesBefore.sharesBalance + expectedShares
187+ );
188+ assertEq (EZETH.balanceOf (bob), traderBalancesBefore.sharesBalance);
189+ } else {
190+ // Ensure that the amount of pooled ether stays the same.
191+ (, uint256 totalPooledEther , ) = getSharePrice ();
192+ assertEq (totalPooledEther, totalBaseSupplyBefore);
193+
194+ // Ensure that the ETH balances were updated correctly.
195+ assertEq (
196+ address (hyperdrive).balance,
197+ hyperdriveBalancesBefore.ETHBalance
198+ );
199+ assertEq (trader.balance, traderBalancesBefore.ETHBalance);
200+
201+ // Ensure that the ezETH shares were updated correctly.
202+ uint256 expectedShares = convertToShares (basePaid);
203+ assertEq (EZETH.totalSupply (), totalSharesBefore);
204+ assertApproxEqAbs (
205+ EZETH.balanceOf (address (hyperdrive)),
206+ hyperdriveBalancesBefore.sharesBalance + expectedShares,
207+ 2 // Higher tolerance due to rounding when converting back into shares.
208+ );
209+ assertApproxEqAbs (
210+ EZETH.balanceOf (trader),
211+ traderBalancesBefore.sharesBalance - expectedShares,
212+ 2 // Higher tolerance due to rounding when converting back into shares.
213+ );
214+ }
215+ }
216+
117217 /// Getters ///
118218
119219 function test_getters () external {
@@ -184,74 +284,6 @@ contract EzETHHyperdriveTest is InstanceTest {
184284
185285 /// Long ///
186286
187- function test_open_long_with_eth (uint256 basePaid ) external {
188- // Bob opens a long by depositing ETH.
189- basePaid = basePaid.normalizeToRange (
190- 2 * hyperdrive.getPoolConfig ().minimumTransactionAmount,
191- HyperdriveUtils.calculateMaxLong (hyperdrive)
192- );
193-
194- // Ensure that we get an UnsupportedToken error. Opening positions
195- // with ETH are not allowed right now. There is a great enough
196- // precision loss when minting ezeth that warrants some investigation
197- // before we can turn this on. Until then, we can zap ezeth into the
198- // pool.
199- vm.expectRevert (IHyperdrive.NotPayable.selector );
200- hyperdrive.openLong { value: basePaid }(
201- basePaid,
202- 0 , // min bond proceeds
203- 0 , // min vault share price
204- IHyperdrive.Options ({
205- destination: bob,
206- asBase: true ,
207- extraData: new bytes (0 )
208- })
209- );
210- }
211-
212- function test_open_long_with_ezeth (uint256 basePaid ) external {
213- vm.stopPrank ();
214- vm.startPrank (bob);
215-
216- // Get some balance information before the deposit.
217- (
218- ,
219- uint256 totalPooledEtherBefore ,
220- uint256 totalSharesBefore
221- ) = getSharePrice ();
222- AccountBalances memory bobBalancesBefore = getAccountBalances (bob);
223- AccountBalances memory hyperdriveBalancesBefore = getAccountBalances (
224- address (hyperdrive)
225- );
226-
227- // Calculate the maximum amount of basePaid we can test.
228- uint256 maxLong = HyperdriveUtils.calculateMaxLong (hyperdrive);
229- uint256 maxEzEth = EZETH.balanceOf (address (bob));
230- uint256 maxRange = maxLong > maxEzEth ? maxEzEth : maxLong;
231- basePaid = basePaid.normalizeToRange (
232- 2 * hyperdrive.getPoolConfig ().minimumTransactionAmount,
233- maxRange
234- );
235-
236- // Convert to shares and approve hyperdrive.
237- uint256 sharesPaid = getAndApproveShares (basePaid);
238-
239- // Open the position.
240- openLong (bob, sharesPaid, false );
241-
242- // Ensure that Renzo's aggregates and the token balances were updated
243- // correctly during the trade.
244- verifyDeposit (
245- bob,
246- basePaid,
247- false ,
248- totalPooledEtherBefore,
249- totalSharesBefore,
250- bobBalancesBefore,
251- hyperdriveBalancesBefore
252- );
253- }
254-
255287 function test_close_long_with_eth (uint256 basePaid ) external {
256288 vm.stopPrank ();
257289 vm.startPrank (bob);
@@ -364,88 +396,6 @@ contract EzETHHyperdriveTest is InstanceTest {
364396
365397 // /// Short ///
366398
367- function test_open_short_with_eth (uint256 shortAmount ) external {
368- vm.stopPrank ();
369- vm.startPrank (bob);
370-
371- // Bob opens a short by depositing ETH.
372- shortAmount = shortAmount.normalizeToRange (
373- 2 * hyperdrive.getPoolConfig ().minimumTransactionAmount,
374- HyperdriveUtils.calculateMaxShort (hyperdrive)
375- );
376-
377- // Ensure that we get an UnsupportedToken error. Opening positions
378- // with ETH are not allowed right now. There is a great enough
379- // precision loss when minting ezeth that warrants some investigation
380- // before we can turn this on. Until then, we can zap ezeth into the
381- // pool.
382- vm.expectRevert (IHyperdrive.NotPayable.selector );
383- hyperdrive.openShort { value: shortAmount }(
384- shortAmount,
385- shortAmount,
386- 0 ,
387- IHyperdrive.Options ({
388- destination: bob,
389- asBase: true ,
390- extraData: new bytes (0 )
391- })
392- );
393- }
394-
395- function test_open_short_with_ezeth (uint256 shortAmount ) external {
396- vm.stopPrank ();
397- vm.startPrank (bob);
398-
399- // Get some balance information before the deposit.
400- (
401- ,
402- uint256 totalPooledEtherBefore ,
403- uint256 totalSharesBefore
404- ) = getSharePrice ();
405- AccountBalances memory bobBalancesBefore = getAccountBalances (bob);
406- AccountBalances memory hyperdriveBalancesBefore = getAccountBalances (
407- address (hyperdrive)
408- );
409-
410- // Calculate the maximum amount we can short.
411- shortAmount = shortAmount.normalizeToRange (
412- 2 * hyperdrive.getPoolConfig ().minimumTransactionAmount,
413- HyperdriveUtils.calculateMaxShort (hyperdrive)
414- );
415-
416- // Bob opens a short by depositing ezETH.
417- EZETH.approve (address (hyperdrive), shortAmount);
418- (, uint256 sharesPaid ) = openShort (bob, shortAmount, false );
419-
420- // Get the base Bob paid for the short.
421- (, uint256 totalPooledEther , uint256 totalShares ) = getSharePrice ();
422- uint256 basePaid = sharesPaid.mulDivDown (totalPooledEther, totalShares);
423-
424- // Ensure that the amount of base paid by the short is reasonable.
425- uint256 realizedRate = HyperdriveUtils.calculateAPRFromRealizedPrice (
426- shortAmount - basePaid,
427- shortAmount,
428- 1e18
429- );
430- assertGt (basePaid, 0 );
431- assertGe (
432- realizedRate,
433- FIXED_RATE.mulDown (POSITION_DURATION_15_DAYS.divDown (365 days))
434- );
435-
436- // Ensure that Renzo's aggregates and the token balances were updated
437- // correctly during the trade.
438- verifyDeposit (
439- bob,
440- basePaid,
441- false ,
442- totalPooledEtherBefore,
443- totalSharesBefore,
444- bobBalancesBefore,
445- hyperdriveBalancesBefore
446- );
447- }
448-
449399 function test_open_short_refunds () external {
450400 vm.startPrank (bob);
451401
@@ -651,76 +601,6 @@ contract EzETHHyperdriveTest is InstanceTest {
651601 );
652602 }
653603
654- function verifyDeposit (
655- address trader ,
656- uint256 basePaid ,
657- bool asBase ,
658- uint256 totalPooledEtherBefore ,
659- uint256 totalSharesBefore ,
660- AccountBalances memory traderBalancesBefore ,
661- AccountBalances memory hyperdriveBalancesBefore
662- ) internal {
663- if (asBase) {
664- // Ensure that the amount of pooled ether increased by the base paid.
665- (, uint256 totalPooledEther , ) = getSharePrice ();
666- assertEq (totalPooledEther, totalPooledEtherBefore + basePaid);
667-
668- // Ensure that the ETH balances were updated correctly.
669- assertEq (
670- address (hyperdrive).balance,
671- hyperdriveBalancesBefore.ETHBalance
672- );
673- assertEq (bob.balance, traderBalancesBefore.ETHBalance - basePaid);
674-
675- // Ensure ezETH shares were updated correctly.
676- assertEq (
677- EZETH.balanceOf (trader),
678- traderBalancesBefore.ezethBalance
679- );
680-
681- // Ensure that the ezETH shares were updated correctly.
682- uint256 expectedShares = RENZO_ORACLE.calculateMintAmount (
683- totalPooledEtherBefore,
684- basePaid,
685- totalSharesBefore
686- );
687- assertEq (EZETH.totalSupply (), totalSharesBefore + expectedShares);
688- assertEq (
689- EZETH.balanceOf (address (hyperdrive)),
690- hyperdriveBalancesBefore.ezethBalance + expectedShares
691- );
692- assertEq (EZETH.balanceOf (bob), traderBalancesBefore.ezethBalance);
693- } else {
694- // Ensure that the amount of pooled ether stays the same.
695- (, uint256 totalPooledEther , ) = getSharePrice ();
696- assertEq (totalPooledEther, totalPooledEtherBefore);
697-
698- // Ensure that the ETH balances were updated correctly.
699- assertEq (
700- address (hyperdrive).balance,
701- hyperdriveBalancesBefore.ETHBalance
702- );
703- assertEq (trader.balance, traderBalancesBefore.ETHBalance);
704-
705- // Ensure that the ezETH shares were updated correctly.
706- uint256 expectedShares = basePaid.mulDivDown (
707- totalSharesBefore,
708- totalPooledEtherBefore
709- );
710- assertEq (EZETH.totalSupply (), totalSharesBefore);
711- assertApproxEqAbs (
712- EZETH.balanceOf (address (hyperdrive)),
713- hyperdriveBalancesBefore.ezethBalance + expectedShares,
714- 1
715- );
716- assertApproxEqAbs (
717- EZETH.balanceOf (trader),
718- traderBalancesBefore.ezethBalance - expectedShares,
719- 1
720- );
721- }
722- }
723-
724604 function verifyEzethWithdrawal (
725605 address trader ,
726606 uint256 baseProceeds ,
@@ -748,12 +628,12 @@ contract EzETHHyperdriveTest is InstanceTest {
748628 );
749629 assertApproxEqAbs (
750630 EZETH.balanceOf (address (hyperdrive)),
751- hyperdriveBalancesBefore.ezethBalance - expectedShares,
631+ hyperdriveBalancesBefore.sharesBalance - expectedShares,
752632 1
753633 );
754634 assertApproxEqAbs (
755635 EZETH.balanceOf (trader),
756- traderBalancesBefore.ezethBalance + expectedShares,
636+ traderBalancesBefore.sharesBalance + expectedShares,
757637 1
758638 );
759639 }
@@ -804,21 +684,6 @@ contract EzETHHyperdriveTest is InstanceTest {
804684 }
805685 }
806686
807- struct AccountBalances {
808- uint256 ezethBalance;
809- uint256 ETHBalance;
810- }
811-
812- function getAccountBalances (
813- address account
814- ) internal view returns (AccountBalances memory ) {
815- return
816- AccountBalances ({
817- ezethBalance: EZETH.balanceOf (account),
818- ETHBalance: account.balance
819- });
820- }
821-
822687 // returns share price information.
823688 function getSharePrice ()
824689 internal
0 commit comments