Skip to content

Commit

Permalink
update comments, change functions order, emit additional event when b…
Browse files Browse the repository at this point in the history
…urn shares
  • Loading branch information
kovalgek committed Apr 24, 2024
1 parent f2ff45e commit 792071c
Show file tree
Hide file tree
Showing 20 changed files with 81 additions and 72 deletions.
4 changes: 2 additions & 2 deletions contracts/BridgingManager.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-FileCopyrightText: 2022 Lido <[email protected]>
// SPDX-FileCopyrightText: 2024 Lido <[email protected]>
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.10;

import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";

/// @author psirex
/// @author psirex, kovalgek
/// @notice Contains administrative methods to retrieve and control the state of the bridging
contract BridgingManager is AccessControl {
/// @dev Stores the state of the bridging
Expand Down
1 change: 0 additions & 1 deletion contracts/lib/DepositDataCodec.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ library DepositDataCodec {
}

function decodeDepositData(bytes calldata buffer) internal pure returns (DepositData memory) {

if (buffer.length < RATE_FIELD_SIZE + TIMESTAMP_FIELD_SIZE) {
revert ErrorDepositDataLength();
}
Expand Down
6 changes: 2 additions & 4 deletions contracts/lib/ECDSA.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// SPDX-FileCopyrightText: 2024 Lido <[email protected]>
// SPDX-License-Identifier: MIT

/// @dev Extracted from:
/// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/cryptography/ECDSA.sol#L53
/// Also it is used in Lido Core Protocol.

pragma solidity 0.8.10;

/// @dev Extracted from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/cryptography/ECDSA.sol#L53
/// Also it is used in Lido on Ethereum protocol: https://github.com/lidofinance/lido-dao/blob/master/contracts/common/lib/ECDSA.sol
library ECDSA {
/**
* @dev Returns the address that signed a hashed message (`hash`).
Expand Down
4 changes: 2 additions & 2 deletions contracts/lib/SignatureChecker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ pragma solidity 0.8.10;

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

/// @dev A copy of SignatureUtils.sol contract from Lido Core Protocol
/// https://github.com/lidofinance/lido-dao/blob/master/contracts/common/lib/SignatureUtils.sol
/// @dev A copy of SignatureUtils.sol library from Lido on Ethereum protocol.
/// https://github.com/lidofinance/lido-dao/blob/master/contracts/common/lib/SignatureUtils.sol
library SignatureChecker {
/**
* @dev The selector of the ERC1271's `isValidSignature(bytes32 hash, bytes signature)` function,
Expand Down
4 changes: 3 additions & 1 deletion contracts/lib/UnstructuredRefStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

pragma solidity 0.8.10;

/// @dev A copy of UnstructuredRefStorage.sol library from Lido on Ethereum protocol.
/// https://github.com/lidofinance/lido-dao/blob/master/contracts/0.8.9/lib/UnstructuredRefStorage.sol
library UnstructuredRefStorage {
function storageMapAddressMapAddressUint256(bytes32 _position) internal pure returns (
mapping(address => mapping(address => uint256)) storage result
Expand All @@ -15,4 +17,4 @@ library UnstructuredRefStorage {
) {
assembly { result.slot := _position }

Check warning on line 18 in contracts/lib/UnstructuredRefStorage.sol

View workflow job for this annotation

GitHub Actions / solhint

Avoid to use inline assembly. It is acceptable only in rare cases
}
}
}
4 changes: 3 additions & 1 deletion contracts/lib/UnstructuredStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

pragma solidity 0.8.10;

/// @dev A copy of UnstructuredStorage.sol library from Lido on Ethereum protocol.
/// https://github.com/lidofinance/lido-dao/blob/master/contracts/0.8.9/lib/UnstructuredStorage.sol
library UnstructuredStorage {
function getStorageBool(bytes32 position) internal view returns (bool data) {
assembly { data := sload(position) }

Check warning on line 10 in contracts/lib/UnstructuredStorage.sol

View workflow job for this annotation

GitHub Actions / solhint

Avoid to use inline assembly. It is acceptable only in rare cases
Expand Down Expand Up @@ -35,4 +37,4 @@ library UnstructuredStorage {
function setStorageUint256(bytes32 position, uint256 data) internal {
assembly { sstore(position, data) }
}
}
}
7 changes: 3 additions & 4 deletions contracts/lido/TokenRateNotifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

pragma solidity 0.8.10;

import {ITokenRatePusher} from "./interfaces/ITokenRatePusher.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import {ITokenRatePusher} from "./interfaces/ITokenRatePusher.sol";

/// @notice An interface to subscribe on the `stETH` token rebases (defined in the `Lido` core contract)
interface IPostTokenRebaseReceiver {
Expand All @@ -23,7 +23,7 @@ interface IPostTokenRebaseReceiver {
}

/// @author kovalgek
/// @notice Notifies all observers when rebase event occures.
/// @notice Notifies all `observers` when rebase event occures.
contract TokenRateNotifier is Ownable, IPostTokenRebaseReceiver {
using ERC165Checker for address;

Expand Down Expand Up @@ -70,7 +70,6 @@ contract TokenRateNotifier is Ownable, IPostTokenRebaseReceiver {
/// @notice Remove a observer at the given `observer_` position
/// @param observer_ observer remove position
function removeObserver(address observer_) external onlyOwner {

uint256 observerIndexToRemove = _observerIndex(observer_);

if (observerIndexToRemove == INDEX_NOT_FOUND) {
Expand Down Expand Up @@ -114,7 +113,7 @@ contract TokenRateNotifier is Ownable, IPostTokenRebaseReceiver {
}

/// @notice Observer length
/// @return Added observers count
/// @return Added `observers` count
function observersLength() external view returns (uint256) {
return observers.length;
}
Expand Down
12 changes: 6 additions & 6 deletions contracts/optimism/L1ERC20ExtendedTokensBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ abstract contract L1ERC20ExtendedTokensBridge is
L2_TOKEN_BRIDGE = l2TokenBridge_;
}

/// @notice required to abstact a way token rate is requested.
function tokenRate() virtual internal view returns (uint256);

/// @inheritdoc IL1ERC20Bridge
function l2TokenBridge() external view returns (address) {
return L2_TOKEN_BRIDGE;
Expand Down Expand Up @@ -118,7 +115,7 @@ abstract contract L1ERC20ExtendedTokensBridge is
emit ERC20WithdrawalFinalized(l1Token_, l2Token_, from_, to_, withdrawnL1TokenAmount, data_);
}

/// @dev Performs the logic for deposits by informing the L2 token bridge contract
/// @notice Performs the logic for deposits by informing the L2 token bridge contract
/// of the deposit and calling safeTransferFrom to lock the L1 funds.
/// @param l1Token_ Address of the L1 ERC20 we are depositing
/// @param l2Token_ Address of the L1 respective L2 ERC20
Expand Down Expand Up @@ -147,7 +144,7 @@ abstract contract L1ERC20ExtendedTokensBridge is
sendCrossDomainMessage(L2_TOKEN_BRIDGE, l2Gas_, message);
}

/// @dev Transfers tokens to the bridge and wraps if needed.
/// @notice Transfers tokens to the bridge and wraps if needed.
/// @param l1Token_ Address of the L1 ERC20 we are depositing.
/// @param from_ Account to pull the deposit from on L1.
/// @param amount_ Amount of the ERC20 to deposit.
Expand All @@ -169,11 +166,14 @@ abstract contract L1ERC20ExtendedTokensBridge is

function _encodeInputDepositData(bytes calldata data_) internal view returns (bytes memory) {
return DepositDataCodec.encodeDepositData(DepositDataCodec.DepositData({
rate: uint96(tokenRate()),
rate: uint96(_tokenRate()),
timestamp: uint40(block.timestamp),
data: data_
}));
}

/// @notice required to abstact a way token rate is requested.
function _tokenRate() virtual internal view returns (uint256);

error ErrorSenderNotEOA();
}
2 changes: 1 addition & 1 deletion contracts/optimism/L1LidoTokensBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ contract L1LidoTokensBridge is L1ERC20ExtendedTokensBridge, Versioned {
_initializeContractVersionTo(2);
}

function tokenRate() override internal view returns (uint256) {
function _tokenRate() override internal view returns (uint256) {
return IERC20WstETH(L1_TOKEN_NON_REBASABLE).stEthPerToken();
}
}
5 changes: 2 additions & 3 deletions contracts/optimism/L2ERC20ExtendedTokensBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {IL1ERC20Bridge} from "./interfaces/IL1ERC20Bridge.sol";
import {IL2ERC20Bridge} from "./interfaces/IL2ERC20Bridge.sol";
import {IERC20Bridged} from "../token/ERC20Bridged.sol";
import {ITokenRateUpdatable} from "../optimism/interfaces/ITokenRateUpdatable.sol";
import {IERC20Wrapper} from "../token/interfaces/IERC20Wrapper.sol";
import {ERC20RebasableBridged} from "../token/ERC20RebasableBridged.sol";
import {BridgingManager} from "../BridgingManager.sol";
import {RebasableAndNonRebasableTokens} from "./RebasableAndNonRebasableTokens.sol";
Expand Down Expand Up @@ -159,7 +158,7 @@ contract L2ERC20ExtendedTokensBridge is
sendCrossDomainMessage(L1_TOKEN_BRIDGE, l1Gas_, message);
}

/// @dev Mints tokens.
/// @notice Mints tokens and returns amount of minted tokens.
/// @param l2Token_ Address of L2 token for which deposit is finalizing.
/// @param to_ Account that token mints for.
/// @param amount_ Amount of token or shares to mint.
Expand All @@ -178,7 +177,7 @@ contract L2ERC20ExtendedTokensBridge is
return amount_;
}

/// @dev Burns tokens
/// @notice Burns tokens and returns amount of non-rebasable token to withdraw.
/// @param l2Token_ Address of L2 token where withdrawal was initiated.
/// @param from_ Account which tokens are burns.
/// @param amount_ Amount of token to burn.
Expand Down
2 changes: 1 addition & 1 deletion contracts/optimism/OpStackTokenRatePusher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

pragma solidity 0.8.10;

import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {CrossDomainEnabled} from "./CrossDomainEnabled.sol";
import {ITokenRatePusher} from "../lido/interfaces/ITokenRatePusher.sol";
import {IERC20WstETH} from "./L1LidoTokensBridge.sol";
import {ITokenRateUpdatable} from "../optimism/interfaces/ITokenRateUpdatable.sol";
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";

/// @author kovalgek
/// @notice Pushes token rate to L2 Oracle.
Expand Down
24 changes: 12 additions & 12 deletions contracts/optimism/RebasableAndNonRebasableTokens.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ contract RebasableAndNonRebasableTokens {
L2_TOKEN_REBASABLE = l2TokenRebasable_;
}

function _isSupportedL1L2TokensPair(address l1Token_, address l2Token_) internal view returns (bool) {
bool isNonRebasablePair = l1Token_ == L1_TOKEN_NON_REBASABLE && l2Token_ == L2_TOKEN_NON_REBASABLE;
bool isRebasablePair = l1Token_ == L1_TOKEN_REBASABLE && l2Token_ == L2_TOKEN_REBASABLE;
return isNonRebasablePair || isRebasablePair;
}

function _getL1Token(address l2Token_) internal view returns (address) {
if (l2Token_ == L2_TOKEN_NON_REBASABLE) { return L1_TOKEN_NON_REBASABLE; }
if (l2Token_ == L2_TOKEN_REBASABLE) { return L1_TOKEN_REBASABLE; }
revert ErrorUnsupportedL2Token(l2Token_);
}

/// @dev Validates that passed l1Token_ and l2Token_ tokens pair is supported by the bridge.
modifier onlySupportedL1L2TokensPair(address l1Token_, address l2Token_) {
if (!_isSupportedL1L2TokensPair(l1Token_, l2Token_)) {
Expand All @@ -59,18 +71,6 @@ contract RebasableAndNonRebasableTokens {
_;
}

function _isSupportedL1L2TokensPair(address l1Token_, address l2Token_) internal view returns (bool) {
bool isNonRebasablePair = l1Token_ == L1_TOKEN_NON_REBASABLE && l2Token_ == L2_TOKEN_NON_REBASABLE;
bool isRebasablePair = l1Token_ == L1_TOKEN_REBASABLE && l2Token_ == L2_TOKEN_REBASABLE;
return isNonRebasablePair || isRebasablePair;
}

function _getL1Token(address l2Token_) internal view returns (address) {
if (l2Token_ == L2_TOKEN_NON_REBASABLE) { return L1_TOKEN_NON_REBASABLE; }
if (l2Token_ == L2_TOKEN_REBASABLE) { return L1_TOKEN_REBASABLE; }
revert ErrorUnsupportedL2Token(l2Token_);
}

error ErrorUnsupportedL1Token(address l1Token);
error ErrorUnsupportedL2Token(address l2Token);
error ErrorUnsupportedL1L2TokensPair(address l1Token, address l2Token);
Expand Down
11 changes: 5 additions & 6 deletions contracts/optimism/TokenRateOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ contract TokenRateOracle is CrossDomainEnabled, ITokenRateOracle, Versioned {
uint64 rateL1Timestamp;
} // occupy a single slot

/// @dev Location of the slot with TokenRateData
bytes32 private constant TOKEN_RATE_DATA_SLOT =
keccak256("TokenRateOracle.TOKEN_RATE_DATA_SLOT");

/// @notice A bridge which can update oracle.
address public immutable L2_ERC20_TOKEN_BRIDGE;

Expand All @@ -53,6 +49,9 @@ contract TokenRateOracle is CrossDomainEnabled, ITokenRateOracle, Versioned {
/// @notice Basic point scale.
uint256 private constant BASIS_POINT_SCALE = 1e4;

/// @dev Location of the slot with TokenRateData
bytes32 private constant TOKEN_RATE_DATA_SLOT = keccak256("TokenRateOracle.TOKEN_RATE_DATA_SLOT");

/// @param messenger_ L2 messenger address being used for cross-chain communications
/// @param l2ERC20TokenBridge_ the bridge address that has a right to updates oracle.
/// @param l1TokenRatePusher_ An address of account on L1 that can update token rate.
Expand Down Expand Up @@ -142,8 +141,8 @@ contract TokenRateOracle is CrossDomainEnabled, ITokenRateOracle, Versioned {
return block.timestamp > _getRateL1Timestamp() + TOKEN_RATE_OUTDATED_DELAY;
}

/// @dev Allow tokenRate deviation from the previous value to be
/// ±`MAX_ALLOWED_TOKEN_RATE_DEVIATION_PER_DAY` BP per day.
/// @notice Allow tokenRate deviation from the previous value to be
/// ±`MAX_ALLOWED_TOKEN_RATE_DEVIATION_PER_DAY` BP per day.
function _isTokenRateWithinAllowedRange(
uint256 newTokenRate_, uint256 newRateL1Timestamp_
) internal view returns (bool) {
Expand Down
4 changes: 2 additions & 2 deletions contracts/token/ERC20Bridged.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ interface IERC20Bridged is IERC20 {
/// @notice Returns bridge which can mint and burn tokens on L2
function bridge() external view returns (address);

/// @notice Creates amount_ tokens and assigns them to account_, increasing the total supply
/// @notice Creates `amount_` tokens and assigns them to `account_`, increasing the total supply
/// @param account_ An address of the account to mint tokens
/// @param amount_ An amount of tokens to mint
function bridgeMint(address account_, uint256 amount_) external;

/// @notice Destroys amount_ tokens from account_, reducing the total supply
/// @notice Destroys `amount_` tokens from `account_`, reducing the total supply
/// @param account_ An address of the account to burn tokens
/// @param amount_ An amount of tokens to burn
function bridgeBurn(address account_, uint256 amount_) external;
Expand Down
1 change: 1 addition & 0 deletions contracts/token/ERC20BridgedPermit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {PermitExtension} from "./PermitExtension.sol";
import {Versioned} from "../utils/Versioned.sol";

/// @author kovalgek
/// @notice extends ERC20Bridged functionality that allows to use permits and versioning.
contract ERC20BridgedPermit is ERC20Bridged, PermitExtension, Versioned {

/// @param name_ The name of the token
Expand Down
7 changes: 4 additions & 3 deletions contracts/token/ERC20RebasableBridged.sol
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ contract ERC20RebasableBridged is IERC20, IERC20Wrapper, IERC20BridgedShares, ER
return (uint256(answer), uint256(rateDecimals));
}

/// @dev Creates amount_ shares and assigns them to account_, increasing the total shares supply
/// @dev Creates `amount_` shares and assigns them to `account_`, increasing the total shares supply
/// @param recipient_ An address of the account to mint shares
/// @param amount_ An amount of shares to mint
function _mintShares(
Expand All @@ -319,7 +319,7 @@ contract ERC20RebasableBridged is IERC20, IERC20Wrapper, IERC20BridgedShares, ER
_emitTransferEvents(address(0), recipient_, tokensAmount ,amount_);
}

/// @dev Destroys amount_ shares from account_, reducing the total shares supply.
/// @dev Destroys `amount_` shares from `account_`, reducing the total shares supply.
/// @param account_ An address of the account to mint shares
/// @param amount_ An amount of shares to mint
function _burnShares(
Expand All @@ -330,7 +330,8 @@ contract ERC20RebasableBridged is IERC20, IERC20Wrapper, IERC20BridgedShares, ER
if (accountShares < amount_) revert ErrorNotEnoughBalance();
_setTotalShares(_getTotalShares() - amount_);
_getShares()[account_] = accountShares - amount_;
emit Transfer(account_, address(0), amount_);
uint256 tokensAmount = _getTokensByShares(amount_);
_emitTransferEvents(account_, address(0), tokensAmount ,amount_);
}

/// @dev Moves `sharesAmount_` shares from `sender_` to `recipient_`.
Expand Down
1 change: 1 addition & 0 deletions contracts/token/ERC20RebasableBridgedPermit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {PermitExtension} from "./PermitExtension.sol";
import {Versioned} from "../utils/Versioned.sol";

/// @author kovalgek
/// @notice extends ERC20RebasableBridged functionality that allows to use permits and versioning.
contract ERC20RebasableBridgedPermit is ERC20RebasableBridged, PermitExtension, Versioned {

/// @param name_ The name of the token
Expand Down
Loading

0 comments on commit 792071c

Please sign in to comment.