Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(contract): applied new solhint rules across l1, l2, and system contracts #473

Merged
merged 15 commits into from
May 16, 2024

Conversation

koloz193
Copy link
Contributor

@koloz193 koloz193 commented May 15, 2024

What ❔

In an effort to make sure our contracts are held up to the highest standards, we applied new solhint rules and fixed the contracts accordingly. Note that while l2 and system contracts have been converted from string based reverts to custom errors, the changes for L1 contracts will come in a separate PR.

Why ❔

Checklist

  • PR title corresponds to the body of PR (we generate changelog entries from PRs).
  • Tests for the changes have been added / updated.
  • Documentation comments have been added / updated.

@koloz193 koloz193 requested a review from dnkolegov May 16, 2024 16:17
Copy link
Collaborator

@dnkolegov dnkolegov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @koloz193 !

@koloz193 koloz193 merged commit 994897b into dev May 16, 2024
22 checks passed
@koloz193 koloz193 deleted the zk-evm-508-testing-solidity-code-style-and-solhint-rules branch May 16, 2024 23:27
@@ -212,7 +215,7 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor {

/// @inheritdoc IExecutor
function commitBatches(
StoredBatchInfo memory _lastCommittedBatchData,
StoredBatchInfo calldata _lastCommittedBatchData,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@koloz193 Can you please check what is the gas differences for your changes?

Copy link
Contributor Author

@koloz193 koloz193 Jun 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i updated the comment on #477 with the report

@@ -34,7 +36,7 @@ contract MailboxFacet is ZkSyncHyperchainBase, IMailbox {
string public constant override getName = "MailboxFacet";

/// @dev Era's chainID
uint256 immutable ERA_CHAIN_ID;
uint256 public immutable ERA_CHAIN_ID;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't be public. This is diamond proxy facet, if you make the function public then it will be a imported as a getter for proxy that is unexpected to be a part of Mailbox and not Getters

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ill add it to the changes for #477

@@ -158,29 +167,29 @@ contract L2StandardERC20 is ERC20PermitUpgradeable, IL2StandardToken, ERC1967Upg

function name() public view override returns (string memory) {
// If method is not available, behave like a token that does not implement this method - revert on call.
if (availableGetters.ignoreName) revert();
if (availableGetters.ignoreName) revert Unimplemented();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there are should be an empty revert, similar if method wasn't implemented at all

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed it in #505

return super.name();
}

function symbol() public view override returns (string memory) {
// If method is not available, behave like a token that does not implement this method - revert on call.
if (availableGetters.ignoreSymbol) revert();
if (availableGetters.ignoreSymbol) revert Unimplemented();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed it in #505

return super.symbol();
}

function decimals() public view override returns (uint8) {
// If method is not available, behave like a token that does not implement this method - revert on call.
if (availableGetters.ignoreDecimals) revert();
if (availableGetters.ignoreDecimals) revert Unimplemented();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed it in #505

"Encoded data length should be 4 times shorter than the original bytecode"
);
if (encodedData.length * 4 != _bytecode.length) {
revert MalformedBytecode(BytecodeError.Length);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be different error for different error reasons.


uint64 encodedChunk = dictionary.readUint64(indexOfEncodedChunk);
uint64 realChunk = _bytecode.readUint64(encodedDataPointer * 4);

require(encodedChunk == realChunk, "Encoded chunk does not match the original bytecode");
if (encodedChunk != realChunk) {
revert ValuesNotEqual(realChunk, encodedChunk);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which values? need to make a specific error for compressor encoded chunks rather than reuse ValuesNotEqual imho


bytes32 derivedKey = stateDiff.readBytes32(52);
uint256 initValue = stateDiff.readUint256(92);
uint256 finalValue = stateDiff.readUint256(124);
require(derivedKey == _compressedStateDiffs.readBytes32(stateDiffPtr), "iw: initial key mismatch");
if (derivedKey != _compressedStateDiffs.readBytes32(stateDiffPtr)) {
revert ValuesNotEqual(uint256(derivedKey), _compressedStateDiffs.readUint256(stateDiffPtr));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

"It is only possible to change from sequential to arbitrary ordering"
);
if (
_nonceOrdering != AccountNonceOrdering.Arbitrary &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be | | instead of && here.

Counterexample for mismatch between new and old code:

  • _nonceOrdering != AccountNonceOrdering.Arbitrary
  • currentInfo.nonceOrdering == AccountNonceOrdering.Sequential

Will fail in the old code and not in the current code.

@@ -165,7 +168,9 @@ contract DefaultAccount is IAccount {
/// @param _signature The signature of the transaction.
/// @return EIP1271_SUCCESS_RETURN_VALUE if the signature is correct. It reverts otherwise.
function _isValidSignature(bytes32 _hash, bytes memory _signature) internal view returns (bool) {
require(_signature.length == 65, "Signature length is incorrect");
if (_signature.length != 65) {
revert InvalidSig(SigField.Length, _signature.length);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InvalidSigLength?

@@ -79,7 +82,9 @@ contract GasBoundCaller {
if (pubdataGas != 0) {
// Here we double check that the additional cost is not higher than the maximum allowed.
// Note, that the `gasleft()` can be spent on pubdata too.
require(pubdataAllowance + gasleft() >= pubdataGas + CALL_RETURN_OVERHEAD, "Not enough gas for pubdata");
if (pubdataAllowance + gasleft() < pubdataGas + CALL_RETURN_OVERHEAD) {
revert InsufficientGas();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be two differnt errors

@@ -36,7 +37,9 @@ library EfficientCall {
/// @return The `keccak256` hash.
function keccak(bytes calldata _data) internal view returns (bytes32) {
bytes memory returnData = staticCall(gasleft(), KECCAK256_SYSTEM_CONTRACT, _data);
require(returnData.length == 32, "keccak256 returned invalid data");
if (returnData.length != 32) {
revert InvalidData();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confusing error, it should Keccak256InvalidReturnData or at least InvalidReturnData

@@ -45,7 +48,9 @@ library EfficientCall {
/// @return The `sha256` hash.
function sha(bytes calldata _data) internal view returns (bytes32) {
bytes memory returnData = staticCall(gasleft(), SHA256_SYSTEM_CONTRACT, _data);
require(returnData.length == 32, "sha returned invalid data");
if (returnData.length != 32) {
revert InvalidData();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sam here

Copy link
Member

@vladbochok vladbochok left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is huge progress, well done! We need to polish it a bit

Yberjon pushed a commit to neotheprogramist/era-contracts that referenced this pull request Aug 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants