Skip to content

Commit feafec4

Browse files
authored
Merge pull request #709 from lidofinance/fix/shapella-upgrade-from-rc0-to-rc1
Feat: shapella upgrade from rc.0 to rc.1 [WIP]
2 parents 73eccd7 + 3c4bb28 commit feafec4

File tree

118 files changed

+2245
-1002
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+2245
-1002
lines changed

.github/workflows/linters.yml

-52
Original file line numberDiff line numberDiff line change
@@ -95,55 +95,3 @@ jobs:
9595
- name: Run Solidity test coverage
9696
run: yarn test:coverage
9797
continue-on-error: false
98-
99-
abi-lint:
100-
name: ABI actuality linter
101-
runs-on: ubuntu-latest
102-
103-
steps:
104-
- uses: actions/checkout@v3
105-
with:
106-
persist-credentials: false
107-
108-
- name: Setup node.js version
109-
uses: actions/setup-node@v3
110-
with:
111-
node-version: 16
112-
113-
- name: Get yarn cache directory path
114-
id: yarn-cache-dir-path
115-
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
116-
117-
- name: Cache yarn cache
118-
id: cache-yarn-cache
119-
uses: actions/cache@v3
120-
with:
121-
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
122-
key: yarn-${{ hashFiles('**/yarn.lock') }}
123-
restore-keys: yarn-${{ hashFiles('**/yarn.lock') }}
124-
125-
- name: Cache node_modules
126-
id: cache-node-modules
127-
uses: actions/cache@v3
128-
with:
129-
path: '**/node_modules'
130-
key: node_modules-${{ hashFiles('**/yarn.lock') }}
131-
restore-keys: node_modules-${{ hashFiles('**/yarn.lock') }}
132-
133-
- name: Install modules
134-
run: yarn
135-
if: |
136-
steps.cache-yarn-cache.outputs.cache-hit != 'true' ||
137-
steps.cache-node-modules.outputs.cache-hit != 'true'
138-
139-
- name: Compile code and extract ABI
140-
run: yarn compile
141-
142-
- name: Check for ABI changes
143-
run: |
144-
git diff --quiet lib/abi && status=clean || status=dirty
145-
if [ $status == "dirty" ]; then
146-
echo "The following ABIs should be commited"
147-
git diff --compact-summary lib/abi
148-
exit 1
149-
fi

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
.vscode
33
**/build/
44
**/node_modules/
5+
**/lib/abi/*.json
56
**/artifacts/
67
**/artifacts-userdoc/
78
.cache

.husky/pre-commit

-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,4 @@ RED_COLOR='\033[0;31m'
55
NO_COLOR='\033[0m'
66

77
yarn compile
8-
git diff --quiet lib/abi || (echo -e "${RED_COLOR}Unstaged ABIs detected${NO_COLOR}"; exit 1)
9-
108
yarn lint

contracts/0.4.24/Lido.sol

+58-24
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ interface IStakingRouter {
112112
external
113113
view
114114
returns (uint256);
115+
116+
function TOTAL_BASIS_POINTS() external view returns (uint256);
115117
}
116118

117119
interface IWithdrawalQueue {
@@ -266,11 +268,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
266268
payable
267269
onlyInit
268270
{
269-
uint256 amount = _bootstrapInitialHolder();
270-
_setBufferedEther(amount);
271-
272-
emit Submitted(INITIAL_TOKEN_HOLDER, amount, 0);
273-
271+
_bootstrapInitialHolder();
274272
_initialize_v2(_lidoLocator, _eip712StETH);
275273
initialized();
276274
}
@@ -340,6 +338,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
340338
*/
341339
function resumeStaking() external {
342340
_auth(STAKING_CONTROL_ROLE);
341+
require(hasInitialized(), "NOT_INITIALIZED");
343342

344343
_resumeStaking();
345344
}
@@ -673,7 +672,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
673672
* Depends on the bunker state and protocol's pause state
674673
*/
675674
function canDeposit() public view returns (bool) {
676-
return !IWithdrawalQueue(getLidoLocator().withdrawalQueue()).isBunkerModeActive() && !isStopped();
675+
return !_withdrawalQueue().isBunkerModeActive() && !isStopped();
677676
}
678677

679678
/**
@@ -682,7 +681,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
682681
*/
683682
function getDepositableEther() public view returns (uint256) {
684683
uint256 bufferedEther = _getBufferedEther();
685-
uint256 withdrawalReserve = IWithdrawalQueue(getLidoLocator().withdrawalQueue()).unfinalizedStETH();
684+
uint256 withdrawalReserve = _withdrawalQueue().unfinalizedStETH();
686685
return bufferedEther > withdrawalReserve ? bufferedEther - withdrawalReserve : 0;
687686
}
688687

@@ -698,7 +697,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
698697
require(msg.sender == locator.depositSecurityModule(), "APP_AUTH_DSM_FAILED");
699698
require(canDeposit(), "CAN_NOT_DEPOSIT");
700699

701-
IStakingRouter stakingRouter = IStakingRouter(locator.stakingRouter());
700+
IStakingRouter stakingRouter = _stakingRouter();
702701
uint256 depositsCount = Math256.min(
703702
_maxDepositsCount,
704703
stakingRouter.getStakingModuleMaxDepositsCount(_stakingModuleId, getDepositableEther())
@@ -730,7 +729,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
730729
* @dev DEPRECATED: use StakingRouter.getWithdrawalCredentials() instead
731730
*/
732731
function getWithdrawalCredentials() external view returns (bytes32) {
733-
return IStakingRouter(getLidoLocator().stakingRouter()).getWithdrawalCredentials();
732+
return _stakingRouter().getWithdrawalCredentials();
734733
}
735734

736735
/**
@@ -746,7 +745,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
746745
* @dev DEPRECATED: use LidoLocator.treasury()
747746
*/
748747
function getTreasury() external view returns (address) {
749-
return getLidoLocator().treasury();
748+
return _treasury();
750749
}
751750

752751
/**
@@ -757,11 +756,11 @@ contract Lido is Versioned, StETHPermit, AragonApp {
757756
* inaccurate because the actual value is truncated here to 1e4 precision.
758757
*/
759758
function getFee() external view returns (uint16 totalFee) {
760-
totalFee = IStakingRouter(getLidoLocator().stakingRouter()).getTotalFeeE4Precision();
759+
totalFee = _stakingRouter().getTotalFeeE4Precision();
761760
}
762761

763762
/**
764-
* @notice Returns current fee distribution
763+
* @notice Returns current fee distribution, values relative to the total fee (getFee())
765764
* @dev DEPRECATED: Now fees information is stored in StakingRouter and
766765
* with higher precision. Use StakingRouter.getStakingFeeAggregateDistribution() instead.
767766
* @return treasuryFeeBasisPoints return treasury fee in TOTAL_BASIS_POINTS (10000 is 100% fee) precision
@@ -780,9 +779,15 @@ contract Lido is Versioned, StETHPermit, AragonApp {
780779
uint16 operatorsFeeBasisPoints
781780
)
782781
{
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
785786
.getStakingFeeAggregateDistributionE4Precision();
787+
788+
insuranceFeeBasisPoints = 0; // explicitly set to zero
789+
treasuryFeeBasisPoints = uint16((treasuryFeeBasisPointsAbs * totalBasisPoints) / totalFee);
790+
operatorsFeeBasisPoints = uint16((operatorsFeeBasisPointsAbs * totalBasisPoints) / totalFee);
786791
}
787792

788793
/*
@@ -941,14 +946,6 @@ contract Lido is Versioned, StETHPermit, AragonApp {
941946
return sharesAmount;
942947
}
943948

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-
952949
/**
953950
* @dev Staking router rewards distribution.
954951
*
@@ -970,7 +967,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
970967
StakingRewardsDistribution memory ret,
971968
IStakingRouter router
972969
) {
973-
router = IStakingRouter(getLidoLocator().stakingRouter());
970+
router = _stakingRouter();
974971

975972
(
976973
ret.recipients,
@@ -1075,7 +1072,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
10751072
}
10761073

10771074
function _transferTreasuryRewards(uint256 treasuryReward) internal {
1078-
address treasury = getLidoLocator().treasury();
1075+
address treasury = _treasury();
10791076
_transferShares(address(this), treasury, treasuryReward);
10801077
_emitTransferAfterMintingShares(treasury, treasuryReward);
10811078
}
@@ -1371,4 +1368,41 @@ contract Lido is Versioned, StETHPermit, AragonApp {
13711368
ret.postTokenRebaseReceiver
13721369
) = getLidoLocator().oracleReportComponentsForLido();
13731370
}
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+
}
13741408
}

contracts/0.4.24/StETH.sol

+20-29
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,8 @@ contract StETH is IERC20, Pausable {
331331
*/
332332
function transferShares(address _recipient, uint256 _sharesAmount) external returns (uint256) {
333333
_transferShares(msg.sender, _recipient, _sharesAmount);
334-
emit TransferShares(msg.sender, _recipient, _sharesAmount);
335334
uint256 tokensAmount = getPooledEthByShares(_sharesAmount);
336-
emit Transfer(msg.sender, _recipient, tokensAmount);
335+
_emitTransferEvents(msg.sender, _recipient, tokensAmount, _sharesAmount);
337336
return tokensAmount;
338337
}
339338

@@ -362,8 +361,7 @@ contract StETH is IERC20, Pausable {
362361

363362
_transferShares(_sender, _recipient, _sharesAmount);
364363
_approve(_sender, msg.sender, currentAllowance.sub(tokensAmount));
365-
emit TransferShares(_sender, _recipient, _sharesAmount);
366-
emit Transfer(_sender, _recipient, tokensAmount);
364+
_emitTransferEvents(_sender, _recipient, tokensAmount, _sharesAmount);
367365
return tokensAmount;
368366
}
369367

@@ -382,8 +380,7 @@ contract StETH is IERC20, Pausable {
382380
function _transfer(address _sender, address _recipient, uint256 _amount) internal {
383381
uint256 _sharesToTransfer = getSharesByPooledEth(_amount);
384382
_transferShares(_sender, _recipient, _sharesToTransfer);
385-
emit Transfer(_sender, _recipient, _amount);
386-
emit TransferShares(_sender, _recipient, _sharesToTransfer);
383+
_emitTransferEvents(_sender, _recipient, _amount, _sharesToTransfer);
387384
}
388385

389386
/**
@@ -507,31 +504,25 @@ contract StETH is IERC20, Pausable {
507504
}
508505

509506
/**
510-
* @notice Mints shares on behalf of 0xdead address,
511-
* the shares amount is equal to the contract's balance. *
512-
*
513-
* Allows to get rid of zero checks for `totalShares` and `totalPooledEther`
514-
* and overcome corner cases.
515-
*
516-
* NB: reverts if the current contract's balance is zero.
517-
*
518-
* @dev must be invoked before using the token
507+
* @dev Emits {Transfer} and {TransferShares} events
519508
*/
520-
function _bootstrapInitialHolder() internal returns (uint256) {
521-
uint256 balance = address(this).balance;
522-
assert(balance != 0);
523-
524-
if (_getTotalShares() == 0) {
525-
// if protocol is empty bootstrap it with the contract's balance
526-
// address(0xdead) is a holder for initial shares
527-
_mintShares(INITIAL_TOKEN_HOLDER, balance);
528-
529-
emit Transfer(0x0, INITIAL_TOKEN_HOLDER, balance);
530-
emit TransferShares(0x0, INITIAL_TOKEN_HOLDER, balance);
509+
function _emitTransferEvents(address _from, address _to, uint _tokenAmount, uint256 _sharesAmount) internal {
510+
emit Transfer(_from, _to, _tokenAmount);
511+
emit TransferShares(_from, _to, _sharesAmount);
512+
}
531513

532-
return balance;
533-
}
514+
/**
515+
* @dev Emits {Transfer} and {TransferShares} events where `from` is 0 address. Indicates mint events.
516+
*/
517+
function _emitTransferAfterMintingShares(address _to, uint256 _sharesAmount) internal {
518+
_emitTransferEvents(address(0), _to, getPooledEthByShares(_sharesAmount), _sharesAmount);
519+
}
534520

535-
return 0;
521+
/**
522+
* @dev Mints shares to INITIAL_TOKEN_HOLDER
523+
*/
524+
function _mintInitialShares(uint256 _sharesAmount) internal {
525+
_mintShares(INITIAL_TOKEN_HOLDER, _sharesAmount);
526+
_emitTransferAfterMintingShares(INITIAL_TOKEN_HOLDER, _sharesAmount);
536527
}
537528
}

contracts/0.4.24/lib/Packed64x4.sol

+26-9
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,43 @@
77
// solhint-disable-next-line
88
pragma solidity ^0.4.24;
99

10+
import {SafeMath} from "@aragon/os/contracts/lib/math/SafeMath.sol";
1011

12+
/// @notice Provides an interface for gas-efficient operations on four uint64 type
13+
/// variables tightly packed into one uint256 variable stored in memory
1114
library Packed64x4 {
15+
using SafeMath for uint256;
1216
using Packed64x4 for Packed64x4.Packed;
1317

14-
// string private constant ERROR_OFFSET_OUT_OF_RANGE = "OFFSET_OUT_OF_RANGE";
1518
uint256 internal constant UINT64_MAX = 0xFFFFFFFFFFFFFFFF;
1619

1720
struct Packed {
1821
uint256 v;
1922
}
2023

21-
//extract n-th uint64 from uint256
22-
function get(Packed memory _self, uint8 n) internal pure returns (uint64 r) {
23-
// require(n < 4, ERROR_OFFSET_OUT_OF_RANGE);
24-
r = uint64((_self.v >> (64 * n)) & UINT64_MAX);
24+
/// @dev Returns uint64 variable stored on position `n` as uint256
25+
function get(Packed memory _self, uint8 n) internal pure returns (uint256 r) {
26+
r = (_self.v >> (64 * n)) & UINT64_MAX;
2527
}
2628

27-
//merge n-th uint64 to uint256
28-
function set(Packed memory _self, uint8 n, uint64 x) internal pure {
29-
// require(n < 4, ERROR_OFFSET_OUT_OF_RANGE);
30-
_self.v = _self.v & ~(UINT64_MAX << (64 * n)) | ((uint256(x) & UINT64_MAX) << (64 * n));
29+
/// @dev Writes value stored in passed `x` variable on position `n`.
30+
/// The passed value must be less or equal to UINT64_MAX.
31+
/// If the passed value exceeds UINT64_MAX method will
32+
/// revert with a "PACKED_OVERFLOW" error message
33+
function set(Packed memory _self, uint8 n, uint256 x) internal pure {
34+
require(x <= UINT64_MAX, "PACKED_OVERFLOW");
35+
_self.v = _self.v & ~(UINT64_MAX << (64 * n)) | ((x & UINT64_MAX) << (64 * n));
36+
}
37+
38+
/// @dev Adds value stored in passed `x` variable to variable stored on position `n`
39+
/// using SafeMath lib
40+
function add(Packed memory _self, uint8 n, uint256 x) internal pure {
41+
set(_self, n, get(_self, n).add(x));
42+
}
43+
44+
/// @dev Subtract value stored in passed `x` variable from variable stored on position `n`
45+
/// using SafeMath lib
46+
function sub(Packed memory _self, uint8 n, uint256 x) internal pure {
47+
set(_self, n, get(_self, n).sub(x));
3148
}
3249
}

contracts/0.4.24/lib/SigningKeys.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ library SigningKeys {
4141
bytes _pubkeys,
4242
bytes _signatures
4343
) internal returns (uint256) {
44-
require(_keysCount > 0 && _startIndex.add(_keysCount - 1) <= UINT64_MAX, "INVALID_KEYS_COUNT");
44+
require(_keysCount > 0 && _startIndex.add(_keysCount) <= UINT64_MAX, "INVALID_KEYS_COUNT");
4545
require(
4646
_pubkeys.length == _keysCount.mul(PUBKEY_LENGTH) && _signatures.length == _keysCount.mul(SIGNATURE_LENGTH),
4747
"LENGTH_MISMATCH"

0 commit comments

Comments
 (0)