Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: low
Invalid

`_executeTransaction` is unprepared to call system contracts other then the Deployer System Contract

Summary

_executeTransaction is unprepared to call system contracts other then the Deployer System Contract, any calls specifying such system contracts in the to field of the transaction struct will fail.

Vulnerability Details

ZkSync has a number of special contracts called system contracts. The ZkSync documentation (https://docs.zksync.io/build/developer-reference/era-contracts/system-contracts) introduces them as follows:

While most of the primitive EVM opcodes can be supported out of the box (i.e. zero-value calls, addition/multiplication/memory/storage management, etc), some of the opcodes are not supported by the VM by default and they are implemented via “system contracts” — these contracts are located in a special kernel space, (...)

Importantly, system contracts can be called only through the SystemContractCaller library. Accordingly, _executeTransaction should check whether the to field of the input parameter transaction corresponds to the address of a system contract and if yes, then should call that system contract via the SystemContractCaller library.

_executeTransaction does check whether to is the address of the deployer system contract, but fails to account for cases when the any other system contract is specified in the to field.

function _executeTransaction(Transaction memory _transaction) internal {
address to = address(uint160(_transaction.to));
uint128 value = Utils.safeCastToU128(_transaction.value);
bytes memory data = _transaction.data;
@> if (to == address(DEPLOYER_SYSTEM_CONTRACT)) {
uint32 gas = Utils.safeCastToU32(gasleft());
@> SystemContractsCaller.systemCallWithPropagatedRevert(gas, to, value, data);
} else {
bool success;
(success,) = to.call{value: value}(data);
if (!success) {
revert MondrianWallet2__ExecutionFailed();
}
}
}

Impact

_executeTransaction will always fail if any other system contract than the deplyer system contract is specified in the to field of the input struct (transaction). MondrianWallet will not be able to interact with other system contracts in this function.

Such calls will revert with a general MondrianWallet2__ExecutionFailed() error.

Tools Used

Manual review, Foundry.

Recommendations

Consider adding conditionals in _executeTransaction for other system contracts like you did for the deployer system contract, so that transactions specifying those system contracts can be executed too.

To the very least, add conditionals that detect if to is a system contract, and revert such calls with a specific error message, like MondrianWallet2__CannotCallThisSystemContract().

Updates

Lead Judging Commences

bube Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.