@@ -112,6 +112,8 @@ interface IStakingRouter {
112
112
external
113
113
view
114
114
returns (uint256 );
115
+
116
+ function TOTAL_BASIS_POINTS () external view returns (uint256 );
115
117
}
116
118
117
119
interface IWithdrawalQueue {
@@ -266,11 +268,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
266
268
payable
267
269
onlyInit
268
270
{
269
- uint256 amount = _bootstrapInitialHolder ();
270
- _setBufferedEther (amount);
271
-
272
- emit Submitted (INITIAL_TOKEN_HOLDER, amount, 0 );
273
-
271
+ _bootstrapInitialHolder ();
274
272
_initialize_v2 (_lidoLocator, _eip712StETH);
275
273
initialized ();
276
274
}
@@ -340,6 +338,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
340
338
*/
341
339
function resumeStaking () external {
342
340
_auth (STAKING_CONTROL_ROLE);
341
+ require (hasInitialized (), "NOT_INITIALIZED " );
343
342
344
343
_resumeStaking ();
345
344
}
@@ -673,7 +672,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
673
672
* Depends on the bunker state and protocol's pause state
674
673
*/
675
674
function canDeposit () public view returns (bool ) {
676
- return ! IWithdrawalQueue ( getLidoLocator (). withdrawalQueue () ).isBunkerModeActive () && ! isStopped ();
675
+ return ! _withdrawalQueue ( ).isBunkerModeActive () && ! isStopped ();
677
676
}
678
677
679
678
/**
@@ -682,7 +681,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
682
681
*/
683
682
function getDepositableEther () public view returns (uint256 ) {
684
683
uint256 bufferedEther = _getBufferedEther ();
685
- uint256 withdrawalReserve = IWithdrawalQueue ( getLidoLocator (). withdrawalQueue () ).unfinalizedStETH ();
684
+ uint256 withdrawalReserve = _withdrawalQueue ( ).unfinalizedStETH ();
686
685
return bufferedEther > withdrawalReserve ? bufferedEther - withdrawalReserve : 0 ;
687
686
}
688
687
@@ -698,7 +697,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
698
697
require (msg .sender == locator.depositSecurityModule (), "APP_AUTH_DSM_FAILED " );
699
698
require (canDeposit (), "CAN_NOT_DEPOSIT " );
700
699
701
- IStakingRouter stakingRouter = IStakingRouter (locator. stakingRouter () );
700
+ IStakingRouter stakingRouter = _stakingRouter ( );
702
701
uint256 depositsCount = Math256.min (
703
702
_maxDepositsCount,
704
703
stakingRouter.getStakingModuleMaxDepositsCount (_stakingModuleId, getDepositableEther ())
@@ -730,7 +729,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
730
729
* @dev DEPRECATED: use StakingRouter.getWithdrawalCredentials() instead
731
730
*/
732
731
function getWithdrawalCredentials () external view returns (bytes32 ) {
733
- return IStakingRouter ( getLidoLocator (). stakingRouter () ).getWithdrawalCredentials ();
732
+ return _stakingRouter ( ).getWithdrawalCredentials ();
734
733
}
735
734
736
735
/**
@@ -746,7 +745,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
746
745
* @dev DEPRECATED: use LidoLocator.treasury()
747
746
*/
748
747
function getTreasury () external view returns (address ) {
749
- return getLidoLocator (). treasury ();
748
+ return _treasury ();
750
749
}
751
750
752
751
/**
@@ -757,11 +756,11 @@ contract Lido is Versioned, StETHPermit, AragonApp {
757
756
* inaccurate because the actual value is truncated here to 1e4 precision.
758
757
*/
759
758
function getFee () external view returns (uint16 totalFee ) {
760
- totalFee = IStakingRouter ( getLidoLocator (). stakingRouter () ).getTotalFeeE4Precision ();
759
+ totalFee = _stakingRouter ( ).getTotalFeeE4Precision ();
761
760
}
762
761
763
762
/**
764
- * @notice Returns current fee distribution
763
+ * @notice Returns current fee distribution, values relative to the total fee (getFee())
765
764
* @dev DEPRECATED: Now fees information is stored in StakingRouter and
766
765
* with higher precision. Use StakingRouter.getStakingFeeAggregateDistribution() instead.
767
766
* @return treasuryFeeBasisPoints return treasury fee in TOTAL_BASIS_POINTS (10000 is 100% fee) precision
@@ -780,9 +779,15 @@ contract Lido is Versioned, StETHPermit, AragonApp {
780
779
uint16 operatorsFeeBasisPoints
781
780
)
782
781
{
783
- insuranceFeeBasisPoints = 0 ; // explicitly set to zero
784
- (treasuryFeeBasisPoints, operatorsFeeBasisPoints) = IStakingRouter (getLidoLocator ().stakingRouter ())
782
+ IStakingRouter stakingRouter = _stakingRouter ();
783
+ uint256 totalBasisPoints = stakingRouter.TOTAL_BASIS_POINTS ();
784
+ uint256 totalFee = stakingRouter.getTotalFeeE4Precision ();
785
+ (uint256 treasuryFeeBasisPointsAbs , uint256 operatorsFeeBasisPointsAbs ) = stakingRouter
785
786
.getStakingFeeAggregateDistributionE4Precision ();
787
+
788
+ insuranceFeeBasisPoints = 0 ; // explicitly set to zero
789
+ treasuryFeeBasisPoints = uint16 ((treasuryFeeBasisPointsAbs * totalBasisPoints) / totalFee);
790
+ operatorsFeeBasisPoints = uint16 ((operatorsFeeBasisPointsAbs * totalBasisPoints) / totalFee);
786
791
}
787
792
788
793
/*
@@ -941,14 +946,6 @@ contract Lido is Versioned, StETHPermit, AragonApp {
941
946
return sharesAmount;
942
947
}
943
948
944
- /**
945
- * @dev Emits {Transfer} and {TransferShares} events where `from` is 0 address. Indicates mint events.
946
- */
947
- function _emitTransferAfterMintingShares (address _to , uint256 _sharesAmount ) internal {
948
- emit Transfer (address (0 ), _to, getPooledEthByShares (_sharesAmount));
949
- emit TransferShares (address (0 ), _to, _sharesAmount);
950
- }
951
-
952
949
/**
953
950
* @dev Staking router rewards distribution.
954
951
*
@@ -970,7 +967,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
970
967
StakingRewardsDistribution memory ret ,
971
968
IStakingRouter router
972
969
) {
973
- router = IStakingRouter ( getLidoLocator (). stakingRouter () );
970
+ router = _stakingRouter ( );
974
971
975
972
(
976
973
ret.recipients,
@@ -1075,7 +1072,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
1075
1072
}
1076
1073
1077
1074
function _transferTreasuryRewards (uint256 treasuryReward ) internal {
1078
- address treasury = getLidoLocator (). treasury ();
1075
+ address treasury = _treasury ();
1079
1076
_transferShares (address (this ), treasury, treasuryReward);
1080
1077
_emitTransferAfterMintingShares (treasury, treasuryReward);
1081
1078
}
@@ -1371,4 +1368,41 @@ contract Lido is Versioned, StETHPermit, AragonApp {
1371
1368
ret.postTokenRebaseReceiver
1372
1369
) = getLidoLocator ().oracleReportComponentsForLido ();
1373
1370
}
1371
+
1372
+ function _stakingRouter () internal view returns (IStakingRouter) {
1373
+ return IStakingRouter (getLidoLocator ().stakingRouter ());
1374
+ }
1375
+
1376
+ function _withdrawalQueue () internal view returns (IWithdrawalQueue) {
1377
+ return IWithdrawalQueue (getLidoLocator ().withdrawalQueue ());
1378
+ }
1379
+
1380
+ function _treasury () internal view returns (address ) {
1381
+ return getLidoLocator ().treasury ();
1382
+ }
1383
+
1384
+ /**
1385
+ * @notice Mints shares on behalf of 0xdead address,
1386
+ * the shares amount is equal to the contract's balance. *
1387
+ *
1388
+ * Allows to get rid of zero checks for `totalShares` and `totalPooledEther`
1389
+ * and overcome corner cases.
1390
+ *
1391
+ * NB: reverts if the current contract's balance is zero.
1392
+ *
1393
+ * @dev must be invoked before using the token
1394
+ */
1395
+ function _bootstrapInitialHolder () internal {
1396
+ uint256 balance = address (this ).balance;
1397
+ assert (balance != 0 );
1398
+
1399
+ if (_getTotalShares () == 0 ) {
1400
+ // if protocol is empty bootstrap it with the contract's balance
1401
+ // address(0xdead) is a holder for initial shares
1402
+ _setBufferedEther (balance);
1403
+ // emitting `Submitted` before Transfer events to preserver events order in tx
1404
+ emit Submitted (INITIAL_TOKEN_HOLDER, balance, 0 );
1405
+ _mintInitialShares (balance);
1406
+ }
1407
+ }
1374
1408
}
0 commit comments