-
Notifications
You must be signed in to change notification settings - Fork 366
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'sb-oz-dec-audit-base' into kl/oz-25jan-l03
- Loading branch information
Showing
1 changed file
with
43 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,10 +12,14 @@ import {ZKChainStorage} from "../state-transition/chain-deps/ZKChainStorage.sol" | |
import {L2WrappedBaseTokenStore} from "../bridge/L2WrappedBaseTokenStore.sol"; | ||
import {IERC20Metadata} from "@openzeppelin/contracts-v4/token/ERC20/extensions/IERC20Metadata.sol"; | ||
|
||
import {UnsafeBytes} from "../common/libraries/UnsafeBytes.sol"; | ||
|
||
/// @title L1GatewayBase | ||
/// @author Matter Labs | ||
/// @custom:security-contact [email protected] | ||
abstract contract L1GatewayBase { | ||
using UnsafeBytes for bytes; | ||
|
||
/// @notice The function to retrieve the chain-specific upgrade data. | ||
/// @param s The pointer to the storage of the chain. | ||
/// @param _wrappedBaseTokenStore The address of the `L2WrappedBaseTokenStore` contract. | ||
|
@@ -43,15 +47,23 @@ abstract contract L1GatewayBase { | |
baseTokenName = string("Ether"); | ||
baseTokenSymbol = string("ETH"); | ||
} else { | ||
try this.getTokenName(_baseTokenAddress) returns (string memory name) { | ||
baseTokenName = name; | ||
} catch { | ||
(string memory stringResult, bool success) = _safeCallTokenMetadata( | ||
_baseTokenAddress, | ||
abi.encodeCall(IERC20Metadata.name, ()) | ||
); | ||
if (success) { | ||
baseTokenName = stringResult; | ||
} else { | ||
baseTokenName = string("Base Token"); | ||
} | ||
|
||
try this.getTokenSymbol(_baseTokenAddress) returns (string memory symbol) { | ||
baseTokenSymbol = symbol; | ||
} catch { | ||
(stringResult, success) = _safeCallTokenMetadata( | ||
_baseTokenAddress, | ||
abi.encodeCall(IERC20Metadata.symbol, ()) | ||
); | ||
if (success) { | ||
baseTokenSymbol = stringResult; | ||
} else { | ||
// "BT" is an acronym for "Base Token" | ||
baseTokenSymbol = string("BT"); | ||
} | ||
|
@@ -69,11 +81,31 @@ abstract contract L1GatewayBase { | |
return abi.encode(additionalForceDeploymentsData); | ||
} | ||
|
||
function getTokenName(address _token) external view returns (string memory) { | ||
return IERC20Metadata(_token).name(); | ||
} | ||
/// @notice Calls a token's metadata method. | ||
/// @dev For the sake of simplicity, we expect that either of the | ||
/// following is true: | ||
/// 1. The token does not support metadata methods | ||
/// 2. The token supports it and returns a `bytes32` string there. | ||
/// 3. The token supports it and returns a correct `string` as a returndata. | ||
/// | ||
/// For all other cases, this function will panic and so such chains would not be | ||
/// deployable. | ||
function _safeCallTokenMetadata(address _token, bytes memory data) internal view returns (string memory, bool) { | ||
// We are not afraid if token returns large calldata, since it affects | ||
// only the deployment of the chain that uses such a malicious token. | ||
(bool callSuccess, bytes memory returnData) = _token.staticcall(data); | ||
|
||
// The failed call most likely means that this method is not supported. | ||
if (!callSuccess) { | ||
return ("", false); | ||
} | ||
|
||
// This case covers non-standard tokens, such as Maker (MKR), that return `bytes32` instead of `string` | ||
if (returnData.length == 32) { | ||
return ("", false); | ||
} | ||
|
||
function getTokenSymbol(address _token) external view returns (string memory) { | ||
return IERC20Metadata(_token).symbol(); | ||
// Note, that the following line will panic in case the token has more non-standard behavior. | ||
return (abi.decode(returnData, (string)), true); | ||
} | ||
} |