Skip to content

Commit

Permalink
Merge pull request #549 from lidofinance/feature/plain-coverage
Browse files Browse the repository at this point in the history
Feat: new accounting oracle report for Lido (feature/shapella-upgrade)
  • Loading branch information
TheDZhon authored Feb 5, 2023
2 parents 4089bd1 + 0ccacaf commit ab0e8b3
Show file tree
Hide file tree
Showing 94 changed files with 2,950 additions and 3,106 deletions.
600 changes: 334 additions & 266 deletions contracts/0.4.24/Lido.sol

Large diffs are not rendered by default.

44 changes: 43 additions & 1 deletion contracts/0.4.24/StETHPermit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,53 @@ pragma solidity 0.4.24;
import {UnstructuredStorage} from "@aragon/os/contracts/common/UnstructuredStorage.sol";

import {ECDSA} from "../common/lib/ECDSA.sol";
import {IERC2612} from "./interfaces/IERC2612.sol";
import {IEIP712} from "../common/interfaces/IEIP712.sol";

import {StETH} from "./StETH.sol";

/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC2612 {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*/
function permit(
address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s
) external;

/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);

/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}


contract StETHPermit is IERC2612, StETH {
using UnstructuredStorage for bytes32;

Expand Down
48 changes: 0 additions & 48 deletions contracts/0.4.24/interfaces/IERC2612.sol

This file was deleted.

2 changes: 1 addition & 1 deletion contracts/0.4.24/lib/Pausable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ contract Pausable {
require(!ACTIVE_FLAG_POSITION.getStorageBool(), "CONTRACT_IS_ACTIVE");
}

function isStopped() external view returns (bool) {
function isStopped() public view returns (bool) {
return !ACTIVE_FLAG_POSITION.getStorageBool();
}

Expand Down
23 changes: 23 additions & 0 deletions contracts/0.4.24/lib/SafeMathSigned256.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: 2023 Lido <[email protected]>

// SPDX-License-Identifier: MIT

// See contracts/COMPILERS.md
pragma solidity 0.4.24;

library SafeMathSigned256 {
function add(int256 a, int256 b) internal pure returns (int256 c) {
c = a + b;

if (a > 0 && b > 0 && c < 0) {
revert ("MATH_SIGNED_OVERFLOW");
} else if (a < 0 && b < 0 && c > 0) {
revert ("MATH_SIGNED_UNDERFLOW");
}
}

function sub(int256 a, int256 b) internal pure returns (int256 c) {
// a - b = a + (-b)
c = add(a, -b);
}
}
13 changes: 6 additions & 7 deletions contracts/0.4.24/nos/NodeOperatorsRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {BytesLib} from "../lib/BytesLib.sol";
import {MemUtils} from "../../common/lib/MemUtils.sol";
import {MinFirstAllocationStrategy} from "../../common/lib/MinFirstAllocationStrategy.sol";
import {SigningKeysStats} from "../lib/SigningKeysStats.sol";

import {Versioned} from "../utils/Versioned.sol";

interface IStETH {
function sharesOf(address _account) external view returns (uint256);
Expand All @@ -34,7 +34,7 @@ interface IStakingModule {
/// @dev Must implement the full version of IStakingModule interface, not only the one declared locally.
/// It's also responsible for distributing rewards to node operators.
/// NOTE: the code below assumes moderate amount of node operators, i.e. up to `MAX_NODE_OPERATORS_COUNT`.
contract NodeOperatorsRegistry is AragonApp, IStakingModule {
contract NodeOperatorsRegistry is AragonApp, IStakingModule, Versioned {
using SafeMath for uint256;
using SafeMath64 for uint64;
using UnstructuredStorage for bytes32;
Expand Down Expand Up @@ -91,8 +91,6 @@ contract NodeOperatorsRegistry is AragonApp, IStakingModule {
//
bytes32 internal constant SIGNING_KEYS_MAPPING_NAME = keccak256("lido.NodeOperatorsRegistry.signingKeysMappingName");

bytes32 internal constant CONTRACT_VERSION_POSITION = keccak256("lido.NodeOperatorsRegistry.contractVersion");

bytes32 internal constant STETH_POSITION = keccak256("lido.NodeOperatorsRegistry.stETH");

/// @dev Total number of operators
Expand Down Expand Up @@ -169,7 +167,8 @@ contract NodeOperatorsRegistry is AragonApp, IStakingModule {
/// For more details see https://github.com/lidofinance/lido-improvement-proposals/blob/develop/LIPS/lip-10.md
function finalizeUpgrade_v2(address _steth, bytes32 _type) external {
require(!isPetrified(), "PETRIFIED");
require(CONTRACT_VERSION_POSITION.getStorageUint256() == 0, "WRONG_BASE_VERSION");
require(hasInitialized(), "NOT_INITIALIZED");
_checkContractVersion(0);
_initialize_v2(_steth, _type);

uint256 totalOperators = getNodeOperatorsCount();
Expand Down Expand Up @@ -212,8 +211,8 @@ contract NodeOperatorsRegistry is AragonApp, IStakingModule {
STETH_POSITION.setStorageAddress(_steth);
TYPE_POSITION.setStorageBytes32(_type);

CONTRACT_VERSION_POSITION.setStorageUint256(2);
emit ContractVersionSet(2);
_setContractVersion(2);

emit StethContractSet(_steth);
emit StakingModuleTypeSet(_type);
}
Expand Down
7 changes: 4 additions & 3 deletions contracts/0.4.24/oracle/LidoOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -240,13 +240,14 @@ contract LidoOracle is AragonApp {
/**
* @notice Called by Lido on each rebase.
*/
function handleRebase(
function handlePostTokenRebase(
uint256 /* reportTimestamp */,
uint256 timeElapsed,
uint256 /* preTotalShares */,
uint256 preTotalEther,
uint256 postTotalShares,
uint256 postTotalEther,
uint256 /* totalSharesMintedAsFees */,
uint256 timeElapsed
uint256 /* totalSharesMintedAsFees */
)
external
{
Expand Down
12 changes: 5 additions & 7 deletions contracts/0.4.24/template/LidoTemplate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ contract LidoTemplate is IsContract {
}

// using loops to save contract size
bytes32[7] memory perms;
bytes32[6] memory perms;

// NodeOperatorsRegistry
perms[0] = _state.operators.MANAGE_SIGNING_KEYS();
Expand All @@ -595,12 +595,10 @@ contract LidoTemplate is IsContract {

// Lido
perms[0] = _state.lido.PAUSE_ROLE();
perms[1] = _state.lido.MANAGE_PROTOCOL_CONTRACTS_ROLE();
perms[2] = _state.lido.BURN_ROLE();
perms[3] = _state.lido.RESUME_ROLE();
perms[4] = _state.lido.STAKING_PAUSE_ROLE();
perms[5] = _state.lido.STAKING_CONTROL_ROLE();
for (i = 0; i < 6; ++i) {
perms[1] = _state.lido.RESUME_ROLE();
perms[2] = _state.lido.STAKING_PAUSE_ROLE();
perms[3] = _state.lido.STAKING_CONTROL_ROLE();
for (i = 0; i < 4; ++i) {
_createPermissionForVoting(acl, _state.lido, perms[i], voting);
}
}
Expand Down
24 changes: 6 additions & 18 deletions contracts/0.4.24/test_helpers/LidoMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,13 @@ contract LidoMock is Lido {
uint256 internal constant UNLIMITED_TOKEN_REBASE = uint256(-1);

function initialize(
address _oracle,
address _treasury,
address _stakingRouterAddress,
address _dsmAddress,
address _executionLayerRewardsVault,
address _withdrawalQueue,
address _lidoLocator,
address _eip712StETH
)
public
{
if (_treasury == address(0)) {
_treasury = new VaultMock();
}
if (_executionLayerRewardsVault == address(0)) {
_executionLayerRewardsVault = new VaultMock();
}
super.initialize(
_oracle,
_treasury,
_stakingRouterAddress,
_dsmAddress,
_executionLayerRewardsVault,
_withdrawalQueue,
_lidoLocator,
_eip712StETH
);

Expand Down Expand Up @@ -83,4 +67,8 @@ contract LidoMock is Lido {
function resetEip712StETH() external {
EIP712_STETH_POSITION.setStorageAddress(0);
}

function burnShares(address _account, uint256 _amount) external {
_burnShares(_account, _amount);
}
}
11 changes: 6 additions & 5 deletions contracts/0.4.24/test_helpers/LidoPushableMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ contract LidoPushableMock is Lido {
uint256 public totalRewards;
bool public distributeFeeCalled;

function initialize(address _oracle) public onlyInit {
_setProtocolContracts(_oracle, _oracle, address(0));
function initialize(address _lidoLocator) public onlyInit {
LIDO_LOCATOR_POSITION.setStorageAddress(_lidoLocator);
_resume();
initialized();
}
Expand Down Expand Up @@ -48,15 +48,16 @@ contract LidoPushableMock is Lido {
distributeFeeCalled = false;
}

function getWithdrawalCredentials() public view returns (bytes32) {
IStakingRouter stakingRouter = IStakingRouter(getStakingRouter());
function getWithdrawalCredentials() external view returns (bytes32) {
IStakingRouter stakingRouter = IStakingRouter(getLidoLocator().stakingRouter());

if (address(stakingRouter) != address(0)) {
return stakingRouter.getWithdrawalCredentials();
}
return bytes32(0);
}

function _distributeFee(uint256 _totalRewards) internal {
function _distributeFee(uint256 _totalRewards) internal returns(uint256 sharesMintedAsFees) {
totalRewards = _totalRewards;
distributeFeeCalled = true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
// SPDX-FileCopyrightText: 2023 Lido <[email protected]>
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.9;
pragma solidity 0.4.24;

import { ILegacyOracle } from "../../oracle/AccountingOracle.sol";

interface ILegacyOracle {
function getBeaconSpec() external view returns (
uint64 epochsPerFrame,
uint64 slotsPerEpoch,
uint64 secondsPerSlot,
uint64 genesisTime
);

contract MockLegacyOracle is ILegacyOracle {
function getLastCompletedEpochId() external view returns (uint256);
}

import "../oracle/LidoOracle.sol";

contract MockLegacyOracle is ILegacyOracle, LidoOracle {
uint64 internal _epochsPerFrame;
uint64 internal _slotsPerEpoch;
uint64 internal _secondsPerSlot;
uint64 internal _genesisTime;
uint256 internal _lastCompletedEpochId;

constructor(
uint64 epochsPerFrame,
uint64 slotsPerEpoch,
uint64 secondsPerSlot,
uint64 genesisTime,
uint256 lastCompletedEpochId
) {
_epochsPerFrame = epochsPerFrame;
_slotsPerEpoch = slotsPerEpoch;
_secondsPerSlot = secondsPerSlot;
_genesisTime = genesisTime;
_lastCompletedEpochId = lastCompletedEpochId;
}

function getBeaconSpec() external view returns (
uint64 epochsPerFrame,
Expand All @@ -40,6 +38,21 @@ contract MockLegacyOracle is ILegacyOracle {
);
}


function setParams(
uint64 epochsPerFrame,
uint64 slotsPerEpoch,
uint64 secondsPerSlot,
uint64 genesisTime,
uint256 lastCompletedEpochId
) external {
_epochsPerFrame = epochsPerFrame;
_slotsPerEpoch = slotsPerEpoch;
_secondsPerSlot = secondsPerSlot;
_genesisTime = genesisTime;
_lastCompletedEpochId = lastCompletedEpochId;

}
function getLastCompletedEpochId() external view returns (uint256) {
return _lastCompletedEpochId;
}
Expand Down
Loading

0 comments on commit ab0e8b3

Please sign in to comment.