From 2ff4e59b74deb0fd0e91076d2c763d0e7cd37bcb Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Wed, 7 Aug 2024 17:00:38 -0300 Subject: [PATCH 01/59] Add Evm Equivalence support --- .../contracts/SystemContractsCaller.sol | 2 +- .../contracts/AccountCodeStorage.sol | 12 +- .../contracts/BootloaderUtilities.sol | 14 +- .../contracts/ComplexUpgrader.sol | 2 +- system-contracts/contracts/Compressor.sol | 2 +- system-contracts/contracts/Constants.sol | 8 +- .../contracts/ContractDeployer.sol | 161 +- system-contracts/contracts/Create2Factory.sol | 2 +- system-contracts/contracts/DefaultAccount.sol | 8 +- system-contracts/contracts/EmptyContract.sol | 2 +- system-contracts/contracts/EvmConstants.sol | 4 + system-contracts/contracts/EvmGasManager.sol | 144 + system-contracts/contracts/EvmInterpreter.yul | 6067 +++++++++++++++++ system-contracts/contracts/GasBoundCaller.sol | 2 +- .../contracts/ImmutableSimulator.sol | 2 +- .../contracts/KnownCodesStorage.sol | 22 +- system-contracts/contracts/L1Messenger.sol | 2 +- system-contracts/contracts/L2BaseToken.sol | 2 +- .../contracts/MsgValueSimulator.sol | 2 +- system-contracts/contracts/NonceHolder.sol | 7 +- .../contracts/PubdataChunkPublisher.sol | 2 +- system-contracts/contracts/SystemContext.sol | 2 +- .../contracts/interfaces/IAccount.sol | 2 +- .../interfaces/IAccountCodeStorage.sol | 4 +- .../contracts/interfaces/IBaseToken.sol | 2 +- .../interfaces/IBootloaderUtilities.sol | 2 +- .../contracts/interfaces/IComplexUpgrader.sol | 2 +- .../contracts/interfaces/ICompressor.sol | 2 +- .../interfaces/IContractDeployer.sol | 16 +- .../interfaces/IImmutableSimulator.sol | 2 +- .../interfaces/IKnownCodesStorage.sol | 4 +- .../contracts/interfaces/IL1Messenger.sol | 2 +- .../contracts/interfaces/IL2StandardToken.sol | 2 +- .../contracts/interfaces/IMailbox.sol | 2 +- .../contracts/interfaces/INonceHolder.sol | 2 +- .../contracts/interfaces/IPaymaster.sol | 2 +- .../contracts/interfaces/IPaymasterFlow.sol | 2 +- .../interfaces/IPubdataChunkPublisher.sol | 2 +- .../contracts/interfaces/ISystemContext.sol | 2 +- .../interfaces/ISystemContextDeprecated.sol | 2 +- .../contracts/interfaces/ISystemContract.sol | 2 +- .../contracts/libraries/EfficientCall.sol | 2 +- .../contracts/libraries/RLPEncoder.sol | 2 +- .../libraries/SystemContractHelper.sol | 63 +- .../libraries/SystemContractsCaller.sol | 6 +- .../contracts/libraries/TransactionHelper.sol | 14 +- .../libraries/UnsafeBytesCalldata.sol | 2 +- .../contracts/libraries/Utils.sol | 63 +- .../contracts/precompiles/CodeOracle.yul | 32 +- .../contracts/test-contracts/Deployable.sol | 2 +- .../test-contracts/GasBoundCallerTester.sol | 2 +- .../contracts/test-contracts/MockContract.sol | 2 +- .../contracts/test-contracts/SystemCaller.sol | 2 +- system-contracts/hardhat.config.ts | 3 +- yarn.lock | 2 +- 55 files changed, 6649 insertions(+), 75 deletions(-) create mode 100644 system-contracts/contracts/EvmConstants.sol create mode 100644 system-contracts/contracts/EvmGasManager.sol create mode 100644 system-contracts/contracts/EvmInterpreter.yul diff --git a/l2-contracts/contracts/SystemContractsCaller.sol b/l2-contracts/contracts/SystemContractsCaller.sol index 36153eb6d..1ac773918 100644 --- a/l2-contracts/contracts/SystemContractsCaller.sol +++ b/l2-contracts/contracts/SystemContractsCaller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {MSG_VALUE_SYSTEM_CONTRACT} from "./L2ContractHelper.sol"; diff --git a/system-contracts/contracts/AccountCodeStorage.sol b/system-contracts/contracts/AccountCodeStorage.sol index 399ea54f5..5833dc9a4 100644 --- a/system-contracts/contracts/AccountCodeStorage.sol +++ b/system-contracts/contracts/AccountCodeStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IAccountCodeStorage} from "./interfaces/IAccountCodeStorage.sol"; import {Utils} from "./libraries/Utils.sol"; @@ -108,6 +108,10 @@ contract AccountCodeStorage is IAccountCodeStorage { codeHash = EMPTY_STRING_KECCAK; } + if (Utils.isCodeHashEVM(codeHash)) { + codeHash = DEPLOYER_SYSTEM_CONTRACT.evmCodeHash(account); + } + return codeHash; } @@ -136,4 +140,10 @@ contract AccountCodeStorage is IAccountCodeStorage { codeSize = Utils.bytecodeLenInBytes(codeHash); } } + + /// @notice Method for detecting whether an address is an EVM contract + function isAccountEVM(address _addr) external view override returns (bool) { + bytes32 bytecodeHash = getRawCodeHash(_addr); + return Utils.isCodeHashEVM(bytecodeHash); + } } diff --git a/system-contracts/contracts/BootloaderUtilities.sol b/system-contracts/contracts/BootloaderUtilities.sol index 5551764dd..dfb4081cd 100644 --- a/system-contracts/contracts/BootloaderUtilities.sol +++ b/system-contracts/contracts/BootloaderUtilities.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IBootloaderUtilities} from "./interfaces/IBootloaderUtilities.sol"; import {Transaction, TransactionHelper, EIP_712_TX_TYPE, LEGACY_TX_TYPE, EIP_2930_TX_TYPE, EIP_1559_TX_TYPE} from "./libraries/TransactionHelper.sol"; @@ -58,7 +58,9 @@ contract BootloaderUtilities is IBootloaderUtilities { encodedGasParam = bytes.concat(encodedGasPrice, encodedGasLimit); } - bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); + bytes memory encodedTo = _transaction.reserved[1] == 0 + ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) + : bytes(hex"80"); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // Encode only the length of the transaction data, and not the data itself, // so as not to copy to memory a potentially huge transaction data twice. @@ -145,7 +147,9 @@ contract BootloaderUtilities is IBootloaderUtilities { bytes memory encodedNonce = RLPEncoder.encodeUint256(_transaction.nonce); bytes memory encodedGasPrice = RLPEncoder.encodeUint256(_transaction.maxFeePerGas); bytes memory encodedGasLimit = RLPEncoder.encodeUint256(_transaction.gasLimit); - bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); + bytes memory encodedTo = _transaction.reserved[1] == 0 + ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) + : bytes(hex"80"); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // solhint-disable-next-line func-named-parameters encodedFixedLengthParams = bytes.concat( @@ -241,7 +245,9 @@ contract BootloaderUtilities is IBootloaderUtilities { bytes memory encodedMaxPriorityFeePerGas = RLPEncoder.encodeUint256(_transaction.maxPriorityFeePerGas); bytes memory encodedMaxFeePerGas = RLPEncoder.encodeUint256(_transaction.maxFeePerGas); bytes memory encodedGasLimit = RLPEncoder.encodeUint256(_transaction.gasLimit); - bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); + bytes memory encodedTo = _transaction.reserved[1] == 0 + ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) + : bytes(hex"80"); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // solhint-disable-next-line func-named-parameters encodedFixedLengthParams = bytes.concat( diff --git a/system-contracts/contracts/ComplexUpgrader.sol b/system-contracts/contracts/ComplexUpgrader.sol index 2f4d886cd..00c4487c3 100644 --- a/system-contracts/contracts/ComplexUpgrader.sol +++ b/system-contracts/contracts/ComplexUpgrader.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IComplexUpgrader} from "./interfaces/IComplexUpgrader.sol"; import {FORCE_DEPLOYER} from "./Constants.sol"; diff --git a/system-contracts/contracts/Compressor.sol b/system-contracts/contracts/Compressor.sol index f52c18ed4..2d8a819ab 100644 --- a/system-contracts/contracts/Compressor.sol +++ b/system-contracts/contracts/Compressor.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {ICompressor, OPERATION_BITMASK, LENGTH_BITS_OFFSET, MAX_ENUMERATION_INDEX_SIZE} from "./interfaces/ICompressor.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index 0f8e2307f..8cb9a9652 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IAccountCodeStorage} from "./interfaces/IAccountCodeStorage.sol"; import {INonceHolder} from "./interfaces/INonceHolder.sol"; @@ -14,6 +14,7 @@ import {ICompressor} from "./interfaces/ICompressor.sol"; import {IComplexUpgrader} from "./interfaces/IComplexUpgrader.sol"; import {IBootloaderUtilities} from "./interfaces/IBootloaderUtilities.sol"; import {IPubdataChunkPublisher} from "./interfaces/IPubdataChunkPublisher.sol"; +import "./EvmGasManager.sol"; /// @dev All the system contracts introduced by zkSync have their addresses /// started from 2^15 in order to avoid collision with Ethereum precompiles. @@ -34,6 +35,7 @@ address constant ECADD_SYSTEM_CONTRACT = address(0x06); address constant ECMUL_SYSTEM_CONTRACT = address(0x07); address constant ECPAIRING_SYSTEM_CONTRACT = address(0x08); +address constant CODE_ORACLE_SYSTEM_CONTRACT = address(SYSTEM_CONTRACTS_OFFSET + 0x12); /// @dev The number of ergs that need to be spent for a single byte of pubdata regardless of the pubdata price. /// This variable is used to ensure the following: @@ -83,6 +85,7 @@ address constant EVENT_WRITER_CONTRACT = address(SYSTEM_CONTRACTS_OFFSET + 0x0d) ICompressor constant COMPRESSOR_CONTRACT = ICompressor(address(SYSTEM_CONTRACTS_OFFSET + 0x0e)); IComplexUpgrader constant COMPLEX_UPGRADER_CONTRACT = IComplexUpgrader(address(SYSTEM_CONTRACTS_OFFSET + 0x0f)); +EvmGasManager constant EVM_GAS_MANAGER = EvmGasManager(address(SYSTEM_CONTRACTS_OFFSET + 0x13)); IPubdataChunkPublisher constant PUBDATA_CHUNK_PUBLISHER = IPubdataChunkPublisher( address(SYSTEM_CONTRACTS_OFFSET + 0x11) @@ -102,6 +105,9 @@ bytes32 constant CREATE2_PREFIX = 0x2020dba91b30cc0006188af794c2fb30dd8520db7e2c /// @dev keccak256("zksyncCreate") bytes32 constant CREATE_PREFIX = 0x63bae3a9951d38e8a3fbb7b70909afc1200610fc5bc55ade242f815974674f23; +/// @dev Prefix used during derivation of account addresses using CREATE2 within the EVM +bytes1 constant CREATE2_EVM_PREFIX = 0xff; + /// @dev Each state diff consists of 156 bytes of actual data and 116 bytes of unused padding, needed for circuit efficiency. uint256 constant STATE_DIFF_ENTRY_SIZE = 272; diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 01009da19..c85e3a47c 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -1,16 +1,18 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {ImmutableData} from "./interfaces/IImmutableSimulator.sol"; import {IContractDeployer} from "./interfaces/IContractDeployer.sol"; -import {CREATE2_PREFIX, CREATE_PREFIX, NONCE_HOLDER_SYSTEM_CONTRACT, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT, FORCE_DEPLOYER, MAX_SYSTEM_CONTRACT_ADDRESS, KNOWN_CODE_STORAGE_CONTRACT, BASE_TOKEN_SYSTEM_CONTRACT, IMMUTABLE_SIMULATOR_SYSTEM_CONTRACT, COMPLEX_UPGRADER_CONTRACT} from "./Constants.sol"; +import {CREATE2_EVM_PREFIX, CREATE2_PREFIX, CREATE_PREFIX, NONCE_HOLDER_SYSTEM_CONTRACT, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT, FORCE_DEPLOYER, MAX_SYSTEM_CONTRACT_ADDRESS, KNOWN_CODE_STORAGE_CONTRACT, BASE_TOKEN_SYSTEM_CONTRACT , IMMUTABLE_SIMULATOR_SYSTEM_CONTRACT, COMPLEX_UPGRADER_CONTRACT, KECCAK256_SYSTEM_CONTRACT} from "./Constants.sol"; import {Utils} from "./libraries/Utils.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; +import {RLPEncoder} from "./libraries/RLPEncoder.sol"; + /** * @author Matter Labs * @custom:security-contact security@matterlabs.dev @@ -25,6 +27,33 @@ contract ContractDeployer is IContractDeployer, ISystemContract { /// @dev For EOA and simple contracts (i.e. not accounts) this value is 0. mapping(address => AccountInfo) internal accountInfo; + enum EvmContractState { + None, + ConstructorPending, + ConstructorCalled, + Deployed + } + + mapping(address => bytes32) public evmCodeHash; + + uint256 public constructorReturnGas; + + function setDeployedCode(uint256 constructorGasLeft, bytes calldata paddedNewDeployedCode) external { + require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender)); + + uint256 bytecodeLen = uint256(bytes32(paddedNewDeployedCode[:32])); + bytes memory trueBytecode = paddedNewDeployedCode[32:32 + bytecodeLen]; + + evmCodeHash[msg.sender] = keccak256(trueBytecode); + constructorReturnGas = constructorGasLeft; + + // ToDO: use efficient call + KNOWN_CODE_STORAGE_CONTRACT.publishEVMBytecode(paddedNewDeployedCode); + + bytes32 codeHash = Utils.hashEVMBytecode(paddedNewDeployedCode); + ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.storeAccountConstructedCodeHash(msg.sender, codeHash); + } + modifier onlySelf() { require(msg.sender == address(this), "Callable only by self"); _; @@ -153,6 +182,38 @@ contract ContractDeployer is IContractDeployer, ISystemContract { return createAccount(_salt, _bytecodeHash, _input, AccountAbstractionVersion.None); } + function createEVM(bytes calldata _initCode) external payable override returns (address) { + // If the account is an EOA, use the min nonce. If it's a contract, use deployment nonce + // Subtract 1 for EOA since the nonce has already been incremented for this transaction + uint256 senderNonce = msg.sender == tx.origin + ? NONCE_HOLDER_SYSTEM_CONTRACT.getMinNonce(msg.sender) - 1 + : NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender) + 1; + address newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); + _evmDeployOnAddress(newAddress, _initCode); + return newAddress; + } + + /// @notice Deploys an EVM contract using address derivation of EVM's `CREATE2` opcode + /// @param _salt The CREATE2 salt + /// @param _initCode The init code for the contract + /// Note: this method may be callable only in system mode, + /// that is checked in the `createAccount` by `onlySystemCall` modifier. + function create2EVM(bytes32 _salt, bytes calldata _initCode) external payable override returns (address) { + // No collision is possible with the zksync's non-EVM CREATE2, since + // the prefixes are different + bytes32 bytecodeHash = EfficientCall.keccak(_initCode); + address newAddress = Utils.getNewAddressCreate2EVM(msg.sender, _salt, bytecodeHash); + + _evmDeployOnAddress(newAddress, _initCode); + + return newAddress; + } + + function createEVMInternal(address _newAddress, bytes calldata _initCode) external payable { + require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender)); + _evmDeployOnAddress(_newAddress, _initCode); + } + /// @notice Deploys a contract account with similar address derivation rules to the EVM's `CREATE2` opcode. /// @param _salt The CREATE2 salt /// @param _bytecodeHash The correctly formatted hash of the bytecode. @@ -273,7 +334,14 @@ contract ContractDeployer is IContractDeployer, ISystemContract { // Do not allow deploying contracts to default accounts that have already executed transactions. require(NONCE_HOLDER_SYSTEM_CONTRACT.getRawNonce(_newAddress) == 0x00, "Account is occupied"); - _performDeployOnAddress(_bytecodeHash, _newAddress, _aaVersion, _input); + _performDeployOnAddress(_bytecodeHash, _newAddress, _aaVersion, _input, true); + } + + function _evmDeployOnAddress(address _newAddress, bytes calldata _initCode) internal { + // Unfortunately we can not provide revert reason as it would break EVM compatibility + // TODO: maybe it is redundant + require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.getCodeHash(uint256(uint160(_newAddress))) == 0x0); + _performDeployOnAddressEVM(_newAddress, AccountAbstractionVersion.None, _initCode, false); } /// @notice Deploy a certain bytecode on the address. @@ -285,7 +353,8 @@ contract ContractDeployer is IContractDeployer, ISystemContract { bytes32 _bytecodeHash, address _newAddress, AccountAbstractionVersion _aaVersion, - bytes calldata _input + bytes calldata _input, + bool _callConstructor ) internal { _ensureBytecodeIsKnown(_bytecodeHash); @@ -301,10 +370,51 @@ contract ContractDeployer is IContractDeployer, ISystemContract { _bytecodeHash: _bytecodeHash, _input: _input, _isSystem: false, - _callConstructor: true + _callConstructor: _callConstructor }); } + function convertToConstructorEVMInput(bytes calldata _input) internal pure returns (bytes memory) { + // With how the contracts work, the calldata to the constuctor must be an ABI-encoded `bytes`. + // This means that it should also contain offset as well as length + uint256 _fullLength = _input.length; + bytes memory extendedInput = new bytes(_input.length + 64); + + assembly { + // "Offset" for the calldata + mstore(add(extendedInput, 0x20), 0x20) + // "Length" + mstore(add(extendedInput, 0x40), _fullLength) + + calldatacopy(add(extendedInput, 0x60), _input.offset, _fullLength) + } + + return extendedInput; + } + + /// @notice Deploy a certain bytecode on the address. + /// @param _newAddress The address of the contract to be deployed. + /// @param _aaVersion The version of the account abstraction protocol to use. + /// @param _input The constructor calldata. + function _performDeployOnAddressEVM( + address _newAddress, + AccountAbstractionVersion _aaVersion, + bytes calldata _input, + bool _callConstructor + ) internal { + AccountInfo memory newAccountInfo; + newAccountInfo.supportedAAVersion = _aaVersion; + // Accounts have sequential nonces by default. + newAccountInfo.nonceOrdering = AccountNonceOrdering.Sequential; + _storeAccountInfo(_newAddress, newAccountInfo); + + // Note, that for contracts the "nonce" is set as deployment nonce. + NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(_newAddress); + + // When constructing they just get the intrepeter bytecode hash in consutrcting mode + _constructEVMContract(msg.sender, _newAddress, _input); + } + /// @notice Check that bytecode hash is marked as known on the `KnownCodeStorage` system contracts function _ensureBytecodeIsKnown(bytes32 _bytecodeHash) internal view { uint256 knownCodeMarker = KNOWN_CODE_STORAGE_CONTRACT.getMarker(_bytecodeHash); @@ -369,4 +479,45 @@ contract ContractDeployer is IContractDeployer, ISystemContract { emit ContractDeployed(_sender, _bytecodeHash, _newAddress); } + + function _constructEVMContract(address _sender, address _newAddress, bytes calldata _input) internal { + // FIXME: this is a temporary limitation. + // To be removed in the future + require(_input.length > 0); + + constructorReturnGas = 0; + + uint256 value = msg.value; + // 1. Transfer the balance to the new address on the constructor call. + if (value > 0) { + BASE_TOKEN_SYSTEM_CONTRACT.transferFromTo(address(this), _newAddress, value); + } + + // 2. Set the constructed code hash on the account + _storeConstructingByteCodeHashOnAddress( + _newAddress, + // Dummy EVM bytecode hash just to call simulator. + // The second byte is `0x01` to indicate that it is being constructed. + bytes32(0x0201000000000000000000000000000000000000000000000000000000000000) + ); + + // 3. Call the constructor on behalf of the account + if (value > 0) { + // Safe to cast value, because `msg.value` <= `uint128.max` due to `MessageValueSimulator` invariant + SystemContractHelper.setValueForNextFarCall(uint128(value)); + } + + // In case of EVM contracts returnData is the new deployed code + bool success = SystemContractHelper.mimicCall(uint32(gasleft()), _newAddress, msg.sender, _input, true, false); + + if (!success) { + assembly { + // Just propagate the error back + returndatacopy(0, 0, returndatasize()) + revert(0, returndatasize()) + } + } + + require(evmCodeHash[_newAddress] != 0x0, "The code hash must be set after the constructor call"); + } } diff --git a/system-contracts/contracts/Create2Factory.sol b/system-contracts/contracts/Create2Factory.sol index 6f68fbb52..eca05180c 100644 --- a/system-contracts/contracts/Create2Factory.sol +++ b/system-contracts/contracts/Create2Factory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {REAL_DEPLOYER_SYSTEM_CONTRACT} from "./Constants.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; diff --git a/system-contracts/contracts/DefaultAccount.sol b/system-contracts/contracts/DefaultAccount.sol index 4c7356dd8..29e64fa89 100644 --- a/system-contracts/contracts/DefaultAccount.sol +++ b/system-contracts/contracts/DefaultAccount.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IAccount, ACCOUNT_VALIDATION_SUCCESS_MAGIC} from "./interfaces/IAccount.sol"; import {TransactionHelper, Transaction} from "./libraries/TransactionHelper.sol"; @@ -136,6 +136,12 @@ contract DefaultAccount is IAccount { bytes calldata data = _transaction.data; uint32 gas = Utils.safeCastToU32(gasleft()); + // TODO: if possible, maybe implment some way to avoid memory copying here. + if (_transaction.reserved[1] != 0) { + DEPLOYER_SYSTEM_CONTRACT.createEVM{value: value}(data); + return; + } + // Note, that the deployment method from the deployer contract can only be called with a "systemCall" flag. bool isSystemCall; if (to == address(DEPLOYER_SYSTEM_CONTRACT) && data.length >= 4) { diff --git a/system-contracts/contracts/EmptyContract.sol b/system-contracts/contracts/EmptyContract.sol index 3f021964a..617b7e070 100644 --- a/system-contracts/contracts/EmptyContract.sol +++ b/system-contracts/contracts/EmptyContract.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/EvmConstants.sol b/system-contracts/contracts/EvmConstants.sol new file mode 100644 index 000000000..0873c5a9f --- /dev/null +++ b/system-contracts/contracts/EvmConstants.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +uint256 constant GAS_DIVISOR = 1; diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol new file mode 100644 index 000000000..64fb86293 --- /dev/null +++ b/system-contracts/contracts/EvmGasManager.sol @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./EvmConstants.sol"; + +import {ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "./Constants.sol"; + +// We consider all the contracts (including system ones) as warm. +uint160 constant PRECOMPILES_END = 0xffff; + +// Denotes that passGas has been consumed +uint256 constant INF_PASS_GAS = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + +contract EvmGasManager { + // We need strust to use `storage` pointers + struct WarmAccountInfo { + bool isWarm; + } + + struct SlotInfo { + bool warm; + uint256 originalValue; + } + + // We dont care about the size, since none of it will be stored/pub;ushed anywya + struct EVMStackFrameInfo { + bool isStatic; + uint256 passGas; + } + + // The following storage variables are not used anywhere explicitly and are just used to obtain the storage pointers + // to use the transient storage with. + mapping(address => WarmAccountInfo) private warmAccounts; + mapping(address => mapping(uint256 => SlotInfo)) private warmSlots; + EVMStackFrameInfo[] private evmStackFrames; + + function tstoreWarmAccount(address account, bool isWarm) internal { + WarmAccountInfo storage ptr = warmAccounts[account]; + + assembly { + tstore(ptr.slot, isWarm) + } + } + + function tloadWarmAccount(address account) internal returns (bool isWarm) { + WarmAccountInfo storage ptr = warmAccounts[account]; + + assembly { + isWarm := tload(ptr.slot) + } + } + + function tstoreWarmSlot(address _account, uint256 _key, SlotInfo memory info) internal { + SlotInfo storage ptr = warmSlots[_account][_key]; + + bool warm = info.warm; + uint256 originalValue = info.originalValue; + + assembly { + tstore(ptr.slot, warm) + tstore(add(ptr.slot, 1), originalValue) + } + } + + function tloadWarmSlot(address _account, uint256 _key) internal view returns (SlotInfo memory info) { + SlotInfo storage ptr = warmSlots[_account][_key]; + + bool isWarm; + uint256 originalValue; + + assembly { + isWarm := tload(ptr.slot) + originalValue := tload(add(ptr.slot, 1)) + } + + info.warm = isWarm; + info.originalValue = originalValue; + } + + modifier onlySystemEvm() { + require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender), "only system evm"); + _; + } + + /* + returns true if the account was already warm + */ + function warmAccount(address account) external payable onlySystemEvm returns (bool wasWarm) { + if (uint160(account) < PRECOMPILES_END) return true; + + wasWarm = tloadWarmAccount(account); + if (!wasWarm) tstoreWarmAccount(account, true); + } + + function isSlotWarm(uint256 _slot) external view returns (bool) { + return tloadWarmSlot(msg.sender, _slot).warm; + } + + function warmSlot(uint256 _slot, uint256 _currentValue) external payable onlySystemEvm returns (bool, uint256) { + SlotInfo memory info = tloadWarmSlot(msg.sender, _slot); + + if (info.warm) { + return (true, info.originalValue); + } + + info.warm = true; + info.originalValue = _currentValue; + + tstoreWarmSlot(msg.sender, _slot, info); + + return (false, _currentValue); + } + + /* + The flow is the following: + When conducting call: + 1. caller calls to an EVM contract pushEVMFrame with the corresponding gas + 2. callee calls consumeEvmFrame to get the gas & make sure that subsequent callee wont be able to read it. + 3. callee sets the return gas + 4. callee calls popEVMFrame to return the gas to the caller & remove the frame + */ + + function pushEVMFrame(uint256 _passGas, bool _isStatic) external { + EVMStackFrameInfo memory frame = EVMStackFrameInfo({passGas: _passGas, isStatic: _isStatic}); + + evmStackFrames.push(frame); + } + + function consumeEvmFrame() external returns (uint256 passGas, bool isStatic) { + if (evmStackFrames.length == 0) return (INF_PASS_GAS, false); + + EVMStackFrameInfo memory frameInfo = evmStackFrames[evmStackFrames.length - 1]; + + passGas = frameInfo.passGas; + isStatic = frameInfo.isStatic; + + // Mark as used + evmStackFrames[evmStackFrames.length - 1].passGas = INF_PASS_GAS; + } + + function popEVMFrame() external { + evmStackFrames.pop(); + } +} diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmInterpreter.yul new file mode 100644 index 000000000..2780a9625 --- /dev/null +++ b/system-contracts/contracts/EvmInterpreter.yul @@ -0,0 +1,6067 @@ +object "EVMInterpreter" { + code { + /// @dev This function is used to get the initCode. + /// @dev It assumes that the initCode has been passed via the calldata and so we use the pointer + /// to obtain the bytecode. + function getConstructorBytecode() { + let bytecodeLengthOffset := BYTECODE_OFFSET() + let bytecodeOffset := add(BYTECODE_OFFSET(), 32) + + loadCalldataIntoActivePtr() + + let size := getActivePtrDataSize() + mstore(bytecodeLengthOffset, size) + + copyActivePtrData(bytecodeOffset, 0, size) + } + + // Note that this function modifies EVM memory and does not restore it. It is expected that + // it is the last called function during execution. + function setDeployedCode(gasLeft, offset, len) { + // This error should never be triggered + // require(offset > 100, "Offset too small"); + + mstore8(sub(offset, 100), 0xd9) + mstore8(sub(offset, 99), 0xeb) + mstore8(sub(offset, 98), 0x76) + mstore8(sub(offset, 97), 0xb2) + mstore(sub(offset, 96), gasLeft) + mstore(sub(offset, 64), 0x40) + mstore(sub(offset, 32), len) + + let success := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, sub(offset, 100), add(len, 100), 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + } + + function padBytecode(offset, len) -> blobOffset, blobLen { + blobOffset := sub(offset, 32) + let trueLastByte := add(offset, len) + + mstore(blobOffset, len) + // clearing out additional bytes + mstore(trueLastByte, 0) + mstore(add(trueLastByte, 32), 0) + + blobLen := add(len, 32) + + if iszero(eq(mod(blobLen, 32), 0)) { + blobLen := add(blobLen, sub(32, mod(blobLen, 32))) + } + + // Not it is divisible by 32, but we must make sure that the number of 32 byte words is odd + if iszero(eq(mod(blobLen, 64), 32)) { + blobLen := add(blobLen, 32) + } + } + + function validateCorrectBytecode(offset, len, gasToReturn) -> returnGas { + if len { + // let firstByte := shr(mload(offset), 248) + // FIXME: Check this. + let firstByte := shr(248, mload(offset)) + if eq(firstByte, 0xEF) { + revert(0, 0) + } + } + + let gasForCode := mul(len, 200) + returnGas := chargeGas(gasToReturn, gasForCode) + } + + function SYSTEM_CONTRACTS_OFFSET() -> offset { + offset := 0x8000 + } + + function ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008002 + } + + function NONCE_HOLDER_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008003 + } + + function DEPLOYER_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008006 + } + + function CODE_ADDRESS_CALL_ADDRESS() -> addr { + addr := 0x000000000000000000000000000000000000FFFE + } + + function CODE_ORACLE_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008012 + } + + function EVM_GAS_MANAGER_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008013 + } + + function CALLFLAGS_CALL_ADDRESS() -> addr { + addr := 0x000000000000000000000000000000000000FFEF + } + + function DEBUG_SLOT_OFFSET() -> offset { + offset := mul(32, 32) + } + + function LAST_RETURNDATA_SIZE_OFFSET() -> offset { + offset := add(DEBUG_SLOT_OFFSET(), mul(5, 32)) + } + + function STACK_OFFSET() -> offset { + offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 32) + } + + function BYTECODE_OFFSET() -> offset { + offset := add(STACK_OFFSET(), mul(1024, 32)) + } + + function INF_PASS_GAS() -> inf { + inf := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + } + + function MAX_POSSIBLE_BYTECODE() -> max { + max := 32000 + } + + function MEM_OFFSET() -> offset { + offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_BYTECODE()) + } + + function MEM_OFFSET_INNER() -> offset { + offset := add(MEM_OFFSET(), 32) + } + + function MAX_POSSIBLE_MEM() -> max { + max := 0x100000 // 1MB + } + + function MAX_MEMORY_FRAME() -> max { + max := add(MEM_OFFSET_INNER(), MAX_POSSIBLE_MEM()) + } + + function MAX_UINT() -> max_uint { + max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + } + + // It is the responsibility of the caller to ensure that ip >= BYTECODE_OFFSET + 32 + function readIP(ip,maxAcceptablePos) -> opcode { + // TODO: Why not do this at the beginning once instead of every time? + if gt(ip, maxAcceptablePos) { + revert(0, 0) + } + + opcode := and(mload(sub(ip, 31)), 0xff) + } + + function readBytes(start, maxAcceptablePos,length) -> value { + if gt(add(start,sub(length,1)), maxAcceptablePos) { + revert(0, 0) + } + value := shr(mul(8,sub(32,length)),mload(start)) + } + + function dupStackItem(sp, evmGas, position) -> newSp, evmGasLeft { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, sub(position, 1))) + + if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + let dup := mload(tempSp) + + newSp := add(sp, 0x20) + mstore(newSp, dup) + } + + function swapStackItem(sp, evmGas, position) -> evmGasLeft { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, position)) + + if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + + let s2 := mload(sp) + let s1 := mload(tempSp) + + mstore(sp, s1) + mstore(tempSp, s2) + } + + function popStackItem(sp, evmGasLeft) -> a, newSp { + // We can not return any error here, because it would break compatibility + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + a := mload(sp) + newSp := sub(sp, 0x20) + } + + function pushStackItem(sp, item, evmGasLeft) -> newSp { + if or(gt(sp, BYTECODE_OFFSET()), eq(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + newSp := add(sp, 0x20) + mstore(newSp, item) + } + + function popStackItemWithoutCheck(sp) -> a, newSp { + a := mload(sp) + newSp := sub(sp, 0x20) + } + + function pushStackItemWithoutCheck(sp, item) -> newSp { + newSp := add(sp, 0x20) + mstore(newSp, item) + } + + function popStackCheck(sp, evmGasLeft, numInputs) { + if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + } + + function popPushStackCheck(sp, evmGasLeft, numInputs) { + let popCheck := lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) + let pushOffset := sub(sp, mul(0x20, numInputs)) + let pushCheck := or(gt(pushOffset, BYTECODE_OFFSET()), eq(pushOffset, BYTECODE_OFFSET())) + if or(popCheck, pushCheck) { + revertWithGas(evmGasLeft) + } + } + + function getCodeAddress() -> addr { + addr := verbatim_0i_1o("code_source") + } + + function loadReturndataIntoActivePtr() { + verbatim_0i_0o("return_data_ptr_to_active") + } + + function loadCalldataIntoActivePtr() { + verbatim_0i_0o("calldata_ptr_to_active") + } + + function getActivePtrDataSize() -> size { + size := verbatim_0i_1o("active_ptr_data_size") + } + + function copyActivePtrData(_dest, _source, _size) { + verbatim_3i_0o("active_ptr_data_copy", _dest, _source, _size) + } + + function ptrAddIntoActive(_dest) { + verbatim_1i_0o("active_ptr_add_assign", _dest) + } + + function ptrShrinkIntoActive(_dest) { + verbatim_1i_0o("active_ptr_shrink_assign", _dest) + } + + function _getRawCodeHash(account) -> hash { + // TODO: Unhardcode this selector + mstore8(0, 0x4d) + mstore8(1, 0xe2) + mstore8(2, 0xe4) + mstore8(3, 0x68) + mstore(4, account) + + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + hash := mload(0) + } + + function _getCodeHash(account) -> hash { + // function getCodeHash(uint256 _input) external view override returns (bytes32) + // 0xe03fe177 + // TODO: Unhardcode this selector + mstore8(0, 0xe0) + mstore8(1, 0x3f) + mstore8(2, 0xe1) + mstore8(3, 0x77) + mstore(4, account) + + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + hash := mload(0) + } + + function getIsStaticFromCallFlags() -> isStatic { + isStatic := verbatim_0i_1o("get_global::call_flags") + // TODO: make it a constnat + isStatic := iszero(iszero(and(isStatic, 0x04))) + } + + // Basically performs an extcodecopy, while returning the length of the bytecode. + function _fetchDeployedCode(addr, _offset, _len) -> codeLen { + codeLen := _fetchDeployedCodeWithDest(addr, 0, _len, _offset) + } + + // Basically performs an extcodecopy, while returning the length of the bytecode. + function _fetchDeployedCodeWithDest(addr, _offset, _len, dest) -> codeLen { + let codeHash := _getRawCodeHash(addr) + + mstore(0, codeHash) + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + // The first word is the true length of the bytecode + returndatacopy(0, 0, 32) + codeLen := mload(0) + + if gt(_len, codeLen) { + _len := codeLen + } + + returndatacopy(dest, add(32,_offset), _len) + } + + // Returns the length of the bytecode. + function _fetchDeployedCodeLen(addr) -> codeLen { + let codeHash := _getRawCodeHash(addr) + + mstore(0, codeHash) + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + + switch iszero(success) + case 1 { + // The code oracle call can only fail in the case where the contract + // we are querying is the current one executing and it has not yet been + // deployed, i.e., if someone calls codesize (or extcodesize(address())) + // inside the constructor. In that case, code length is zero. + codeLen := 0 + } + default { + // The first word is the true length of the bytecode + returndatacopy(0, 0, 32) + codeLen := mload(0) + } + + } + + function getDeployedBytecode() { + let codeLen := _fetchDeployedCode( + getCodeAddress(), + add(BYTECODE_OFFSET(), 32), + MAX_POSSIBLE_BYTECODE() + ) + + mstore(BYTECODE_OFFSET(), codeLen) + } + + function consumeEvmFrame() -> passGas, isStatic, callerEVM { + // function consumeEvmFrame() external returns (uint256 passGas, bool isStatic) + // TODO: Unhardcode selector + mstore8(0, 0x04) + mstore8(1, 0xc1) + mstore8(2, 0x4e) + mstore8(3, 0x9e) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 4, 0, 64) + + if iszero(success) { + // Should never happen + revert(0, 0) + } + + passGas := mload(0) + isStatic := mload(32) + + if iszero(eq(passGas, INF_PASS_GAS())) { + callerEVM := true + } + } + + function chargeGas(prevGas, toCharge) -> gasRemaining { + if lt(prevGas, toCharge) { + revertWithGas(0) + } + + gasRemaining := sub(prevGas, toCharge) + } + + function getMax(a, b) -> max { + max := b + if gt(a, b) { + max := a + } + } + + function getMin(a, b) -> min { + min := b + if lt(a, b) { + min := a + } + } + + function bitLength(n) -> bitLen { + for { } gt(n, 0) { } { // while(n > 0) + if iszero(n) { + bitLen := 1 + break + } + n := shr(1, n) + bitLen := add(bitLen, 1) + } + } + + function bitMaskFromBytes(nBytes) -> bitMask { + bitMask := sub(exp(2, mul(nBytes, 8)), 1) // 2**(nBytes*8) - 1 + } + // The gas cost mentioned here is purely the cost of the contract, + // and does not consider the cost of the call itself nor the instructions + // to put the parameters in memory. + // Take into account MEM_OFFSET_INNER() when passing the argsOfsset + function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { + switch addr + case 0x01 { // ecRecover + gasToCharge := 3000 + } + case 0x02 { // SHA2-256 + gasToCharge := 60 + let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 + gasToCharge := add(gasToCharge, mul(12, dataWordSize)) + } + case 0x03 { // RIPEMD-160 + gasToCharge := 600 + let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 + gasToCharge := add(gasToCharge, mul(120, dataWordSize)) + } + case 0x04 { // identity + gasToCharge := 15 + let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 + gasToCharge := add(gasToCharge, mul(3, dataWordSize)) + } + // [0; 31] (32 bytes) Bsize Byte size of B + // [32; 63] (32 bytes) Esize Byte size of E + // [64; 95] (32 bytes) Msize Byte size of M + /* + def calculate_iteration_count(exponent_length, exponent): + iteration_count = 0 + if exponent_length <= 32 and exponent == 0: iteration_count = 0 + elif exponent_length <= 32: iteration_count = exponent.bit_length() - 1 + elif exponent_length > 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1) + return max(iteration_count, 1) + def calculate_gas_cost(base_length, modulus_length, exponent_length, exponent): + multiplication_complexity = calculate_multiplication_complexity(base_length, modulus_length) + iteration_count = calculate_iteration_count(exponent_length, exponent) + return max(200, math.floor(multiplication_complexity * iteration_count / 3)) + */ + // modexp gas cost EIP below + // https://eips.ethereum.org/EIPS/eip-2565 + case 0x05 { // modexp + let mulComplex + let Bsize := mload(argsOffset) + let Esize := mload(add(argsOffset, 0x20)) + + { + let words := getMax(Bsize, mload(add(argsOffset, 0x40))) // shr(3, x) == x/8 + if and(lt(words, 64), eq(words, 64)){ + // if x <= 64: return x ** 2 + mulComplex := mul(words, words) + } + if and(and(lt(words, 1024), eq(words, 1024)), gt(words, 64)){ + // elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072 + mulComplex := sub(add(shr(2, mul(words, words)), mul(96, words)), 3072) + } + if gt(words, 64) { + // else: return x ** 2 // 16 + 480 * x - 199680 + mulComplex := sub(add(shr(4, mul(words, words)), mul(480, words)), 199680) + } + } + + // [96 + Bsize; 96 + Bsize + Esize] E + let exponentFirst256, exponentIsZero, exponentBitLen + if or(lt(Esize, 32), eq(Esize, 32)) { + // Maybe there isn't exactly 32 bytes, so a mask should be applied + exponentFirst256 := mload(add(add(argsOffset, 0x60), Bsize)) + exponentBitLen := bitLength(exponentFirst256) + exponentIsZero := iszero(and(exponentFirst256, bitMaskFromBytes(Esize))) + } + if gt(Esize, 32) { + exponentFirst256 := mload(add(add(argsOffset, 0x60), Bsize)) + exponentIsZero := iszero(exponentFirst256) + let exponentNext + // This is done because the first 32bytes of the exponent were loaded + for { let i := 0 } lt(i, div(Esize, 32)) { i := add(i, 1) Esize := sub(Esize, 32) } { // check every 32bytes + // Maybe there isn't exactly 32 bytes, so a mask should be applied + exponentNext := mload(add(add(add(argsOffset, 0x60), Bsize), add(mul(i, 32), 32))) + exponentBitLen := add(bitLength(exponentNext), mul(mul(32, 8), add(i, 1))) + if iszero(iszero(and(exponentNext, bitMaskFromBytes(Esize)))) { + exponentIsZero := false + } + } + } + + // if exponent_length <= 32 and exponent == 0: iteration_count = 0 + // return max(iteration_count, 1) + let iterationCount := 1 + // elif exponent_length <= 32: iteration_count = exponent.bit_length() - 1 + if and(lt(Esize, 32), iszero(exponentIsZero)) { + iterationCount := sub(exponentBitLen, 1) + } + // elif exponent_length > 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1) + if gt(Esize, 32) { + iterationCount := add(mul(8, sub(Esize, 32)), sub(bitLength(and(exponentFirst256, MAX_UINT())), 1)) + } + + gasToCharge := getMax(200, div(mul(mulComplex, iterationCount), 3)) + } + // ecAdd ecMul ecPairing EIP below + // https://eips.ethereum.org/EIPS/eip-1108 + case 0x06 { // ecAdd + // The gas cost is fixed at 150. However, if the input + // does not allow to compute a valid result, all the gas sent is consumed. + gasToCharge := 150 + } + case 0x07 { // ecMul + // The gas cost is fixed at 6000. However, if the input + // does not allow to compute a valid result, all the gas sent is consumed. + gasToCharge := 6000 + } + // 35,000 * k + 45,000 gas, where k is the number of pairings being computed. + // The input must always be a multiple of 6 32-byte values. + case 0x08 { // ecPairing + gasToCharge := 45000 + let k := div(argsSize, 0xC0) // 0xC0 == 6*32 + gasToCharge := add(gasToCharge, mul(k, 35000)) + } + case 0x09 { // blake2f + // argsOffset[0; 3] (4 bytes) Number of rounds (big-endian uint) + gasToCharge := and(mload(argsOffset), 0xFFFFFFFF) // last 4bytes + } + default { + gasToCharge := 0 + } + } + + function checkMemOverflow(location, evmGasLeft) { + if gt(location, MAX_MEMORY_FRAME()) { + mstore(0, evmGasLeft) + revert(0, 32) + } + } + + function checkMultipleOverflow(data1, data2, data3, evmGasLeft) { + checkOverflow(data1, data2, evmGasLeft) + checkOverflow(data1, data3, evmGasLeft) + checkOverflow(data2, data3, evmGasLeft) + checkOverflow(add(data1, data2), data3, evmGasLeft) + } + + function checkOverflow(data1, data2, evmGasLeft) { + if lt(add(data1, data2), data2) { + revertWithGas(evmGasLeft) + } + } + + function revertWithGas(evmGasLeft) { + mstore(0, evmGasLeft) + revert(0, 32) + } + + // This function can overflow, it is the job of the caller to ensure that it does not. + // The argument to this function is the offset into the memory region IN BYTES. + function expandMemory(newSize) -> gasCost { + let oldSizeInWords := mload(MEM_OFFSET()) + + // The add 31 here before dividing is there to account for misaligned + // memory expansions, where someone calls this with a newSize that is not + // a multiple of 32. For instance, if someone calls it with an offset of 33, + // the new size in words should be 2, not 1, but dividing by 32 will give 1. + // Adding 31 solves it. + let newSizeInWords := div(add(newSize, 31), 32) + + if gt(newSizeInWords, oldSizeInWords) { + let new_minus_old := sub(newSizeInWords, oldSizeInWords) + gasCost := add(mul(3,new_minus_old), div(mul(new_minus_old,add(newSizeInWords,oldSizeInWords)),512)) + + mstore(MEM_OFFSET(), newSizeInWords) + } + } + + // Essentially a NOP that will not get optimized away by the compiler + function $llvm_NoInline_llvm$_unoptimized() { + pop(1) + } + + function printHex(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebde) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() + } + + function printString(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdf) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() + } + + function isSlotWarm(key) -> isWarm { + // TODO: Unhardcode this selector 0x482d2e74 + mstore8(0, 0x48) + mstore8(1, 0x2d) + mstore8(2, 0x2e) + mstore8(3, 0x74) + mstore(4, key) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + isWarm := mload(0) + } + + function warmSlot(key,currentValue) -> isWarm, originalValue { + // TODO: Unhardcode this selector 0xbdf78160 + mstore8(0, 0xbd) + mstore8(1, 0xf7) + mstore8(2, 0x81) + mstore8(3, 0x60) + mstore(4, key) + mstore(36,currentValue) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 64) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + isWarm := mload(0) + originalValue := mload(32) + } + + function MAX_SYSTEM_CONTRACT_ADDR() -> ret { + ret := 0x000000000000000000000000000000000000ffff + } + + /// @dev Checks whether an address is an EOA (i.e. has not code deployed on it) + /// @param addr The address to check + function isEOA(addr) -> ret { + ret := 0 + if gt(addr, MAX_SYSTEM_CONTRACT_ADDR()) { + ret := iszero(_getRawCodeHash(addr)) + } + } + + function getNewAddress(addr) -> newAddr { + let digest, nonce, addressEncoded, nonceEncoded, nonceEncodedLength, listLength, listLengthEconded + + nonce := getNonce(addr) + + addressEncoded := and( + add(addr, shl(160, 0x94)), + 0xffffffffffffffffffffffffffffffffffffffffff + ) + + nonceEncoded := nonce + nonceEncodedLength := 1 + if iszero(nonce) { + nonceEncoded := 128 + } + // The nonce has 4 bytes + if gt(nonce, 0xFFFFFF) { + nonceEncoded := shl(32, 0x84) + nonceEncoded := add(nonceEncoded, nonce) + nonceEncodedLength := 5 + } + // The nonce has 3 bytes + if and(gt(nonce, 0xFFFF), lt(nonce, 0x1000000)) { + nonceEncoded := shl(24, 0x83) + nonceEncoded := add(nonceEncoded, nonce) + nonceEncodedLength := 4 + } + // The nonce has 2 bytes + if and(gt(nonce, 0xFF), lt(nonce, 0x10000)) { + nonceEncoded := shl(16, 0x82) + nonceEncoded := add(nonceEncoded, nonce) + nonceEncodedLength := 3 + } + // The nonce has 1 byte and it's in [0x80, 0xFF] + if and(gt(nonce, 0x7F), lt(nonce, 0x100)) { + nonceEncoded := shl(8, 0x81) + nonceEncoded := add(nonceEncoded, nonce) + nonceEncodedLength := 2 + } + + listLength := add(21, nonceEncodedLength) + listLengthEconded := add(listLength, 0xC0) + + let arrayLength := add(168, mul(8, nonceEncodedLength)) + + digest := add( + shl(arrayLength, listLengthEconded), + add( + shl( + mul(8, nonceEncodedLength), + addressEncoded + ), + nonceEncoded + ) + ) + + mstore(0, shl(sub(248, arrayLength), digest)) + + newAddr := and( + keccak256(0, add(div(arrayLength, 8), 1)), + 0xffffffffffffffffffffffffffffffffffffffff + ) + } + + function incrementNonce(addr) { + mstore8(0, 0x30) + mstore8(1, 0x63) + mstore8(2, 0x95) + mstore8(3, 0xc6) + mstore(4, addr) + + let result := call(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 0, 36, 0, 0) + + if iszero(result) { + revert(0, 0) + } + } + + function ensureAcceptableMemLocation(location) { + if gt(location,MAX_POSSIBLE_MEM()) { + revert(0,0) // Check if this is whats needed + } + } + + function addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) -> newOffset,newSize { + newOffset := offset + newSize := size + if eq(isCallerEVM,1) { + // include gas + let previousValue := mload(sub(offset,32)) + mstore(sub(offset,32),evmGasLeft) + //mstore(sub(offset,32),previousValue) // Im not sure why this is needed, it was like this in the solidity code, + // but it appears to rewrite were we want to store the gas + + newOffset := sub(offset, 32) + newSize := add(size, 32) + } + } + + function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { + // TODO: Unhardcode this selector 0x8db2ba78 + mstore8(0, 0x8d) + mstore8(1, 0xb2) + mstore8(2, 0xba) + mstore8(3, 0x78) + mstore(4, addr) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + isWarm := mload(0) + } + + function getNonce(addr) -> nonce { + mstore8(0, 0xfb) + mstore8(1, 0x1a) + mstore8(2, 0x9a) + mstore8(3, 0x57) + mstore(4, addr) + + let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(result) { + revert(0, 0) + } + + nonce := mload(0) + } + + function getRawNonce(addr) -> nonce { + mstore8(0, 0x5a) + mstore8(1, 0xa9) + mstore8(2, 0xb6) + mstore8(3, 0xb5) + mstore(4, addr) + + let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(result) { + revert(0, 0) + } + + nonce := mload(0) + } + + function _isEVM(_addr) -> isEVM { + // bytes4 selector = ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM.selector; (0x8c040477) + // function isAccountEVM(address _addr) external view returns (bool); + // IAccountCodeStorage constant ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT = IAccountCodeStorage( + // address(SYSTEM_CONTRACTS_OFFSET + 0x02) + // ); + + mstore8(0, 0x8c) + mstore8(1, 0x04) + mstore8(2, 0x04) + mstore8(3, 0x77) + mstore(4, _addr) + + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + isEVM := mload(0) + } + + function _pushEVMFrame(_passGas, _isStatic) { + // function pushEVMFrame(uint256 _passGas, bool _isStatic) external + let selector := 0xead77156 + + mstore8(0, 0xea) + mstore8(1, 0xd7) + mstore8(2, 0x71) + mstore8(3, 0x56) + mstore(4, _passGas) + mstore(36, _isStatic) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 0) + if iszero(success) { + // This error should never happen + revert(0, 0) + } + } + + function _popEVMFrame() { + // function popEVMFrame() external + // 0xe467d2f0 + let selector := 0xe467d2f0 + + mstore8(0, 0xe4) + mstore8(1, 0x67) + mstore8(2, 0xd2) + mstore8(3, 0xf0) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 4, 0, 0) + if iszero(success) { + // This error should never happen + revert(0, 0) + } + } + + // Each evm gas is 5 zkEVM one + // FIXME: change this variable to reflect real ergs : gas ratio + function GAS_DIVISOR() -> gas_div { gas_div := 5 } + function EVM_GAS_STIPEND() -> gas_stipend { gas_stipend := shl(30, 1) } // 1 << 30 + function OVERHEAD() -> overhead { overhead := 2000 } + + // From precompiles/CodeOracle + function DECOMMIT_COST_PER_WORD() -> cost { cost := 4 } + function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 + + function _calcEVMGas(_zkevmGas) -> calczkevmGas { + calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) + } + + function getEVMGas() -> evmGas { + let _gas := gas() + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) + + switch lt(_gas, requiredGas) + case 1 { + evmGas := 0 + } + default { + evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) + } + } + + function _getZkEVMGas(_evmGas, addr) -> zkevmGas { + zkevmGas := mul(_evmGas, GAS_DIVISOR()) + let byteSize := extcodesize(addr) + let should_ceil := mod(byteSize, 32) + if gt(should_ceil, 0) { + byteSize := add(byteSize, sub(32, should_ceil)) + } + let decommitGasCost := mul(div(byteSize,32), DECOMMIT_COST_PER_WORD()) + zkevmGas := sub(zkevmGas, decommitGasCost) + if gt(zkevmGas, UINT32_MAX()) { + zkevmGas := UINT32_MAX() + } + } + + function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft{ + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + let rtsz := returndatasize() + + loadReturndataIntoActivePtr() + + // if (rtsz > 31) + switch gt(rtsz, 31) + case 0 { + // Unexpected return data. + _gasLeft := 0 + _eraseReturndataPointer() + } + default { + returndatacopy(0, 0, 32) + _gasLeft := mload(0) + + // We copy as much returndata as possible without going over the + // returndata size. + switch lt(sub(rtsz, 32), _outputLen) + case 0 { returndatacopy(_outputOffset, 32, _outputLen) } + default { returndatacopy(_outputOffset, 32, sub(rtsz, 32)) } + + mstore(lastRtSzOffset, sub(rtsz, 32)) + + // Skip the returnData + ptrAddIntoActive(32) + } + } + + function _eraseReturndataPointer() { + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + + let activePtrSize := getActivePtrDataSize() + ptrShrinkIntoActive(and(activePtrSize, 0xFFFFFFFF))// uint32(activePtrSize) + mstore(lastRtSzOffset, 0) + } + + function _saveReturndataAfterZkEVMCall() { + loadReturndataIntoActivePtr() + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + + mstore(lastRtSzOffset, returndatasize()) + } + + function performStaticCall(oldSp,evmGasLeft) -> extraCost, sp { + let gasToPass,addr, argsOffset, argsSize, retOffset, retSize + + popStackCheck(oldSp, evmGasLeft, 6) + gasToPass, sp := popStackItemWithoutCheck(oldSp) + addr, sp := popStackItemWithoutCheck(sp) + argsOffset, sp := popStackItemWithoutCheck(sp) + argsSize, sp := popStackItemWithoutCheck(sp) + retOffset, sp := popStackItemWithoutCheck(sp) + retSize, sp := popStackItemWithoutCheck(sp) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + checkMultipleOverflow(argsOffset,argsSize,MEM_OFFSET_INNER(), evmGasLeft) + checkMultipleOverflow(retOffset, retSize,MEM_OFFSET_INNER(), evmGasLeft) + + checkMemOverflow(add(add(argsOffset, argsSize), MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflow(add(add(retOffset, retSize), MEM_OFFSET_INNER()), evmGasLeft) + + extraCost := 0 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + extraCost := 2500 + } + + { + let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) + extraCost := add(extraCost,maxExpand) + } + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + if gt(gasToPass, maxGasToPass) { + gasToPass := maxGasToPass + } + + let frameGasLeft + let success + if _isEVM(addr) { + _pushEVMFrame(gasToPass, true) + // TODO Check the following comment from zkSync .sol. + // We can not just pass all gas here to prevert overflow of zkEVM gas counter + success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, 0, 0) + + frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + _popEVMFrame() + } + + // zkEVM native + if iszero(_isEVM(addr)) { + gasToPass := _getZkEVMGas(gasToPass, addr) + let zkevmGasBefore := gas() + success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, add(MEM_OFFSET_INNER(), retOffset), retSize) + _saveReturndataAfterZkEVMCall() + + let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + + frameGasLeft := 0 + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) + } + } + + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) + sp := pushStackItem(sp, success, evmGasLeft) + } + function capGas(evmGasLeft,oldGasToPass) -> gasToPass { + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + gasToPass := oldGasToPass + if gt(oldGasToPass, maxGasToPass) { + gasToPass := maxGasToPass + } + } + + function getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) -> maxExpand{ + maxExpand := add(retOffset, retSize) + switch lt(maxExpand,add(argsOffset, argsSize)) + case 0 { + maxExpand := expandMemory(maxExpand) + } + default { + maxExpand := expandMemory(add(argsOffset, argsSize)) + } + } + + function _performCall(addr,gasToPass,value,argsOffset,argsSize,retOffset,retSize,isStatic) -> success, frameGasLeft, gasToPassNew{ + gasToPassNew := gasToPass + let is_evm := _isEVM(addr) + if isStatic { + if value { + revertWithGas(gasToPassNew) + } + success, frameGasLeft:= _performStaticCall( + is_evm, + gasToPassNew, + addr, + argsOffset, + argsSize, + retOffset, + retSize + ) + } + + if and(is_evm, iszero(isStatic)) { + _pushEVMFrame(gasToPassNew, isStatic) + success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + _popEVMFrame() + } + + // zkEVM native + if and(iszero(is_evm), iszero(isStatic)) { + gasToPassNew := _getZkEVMGas(gasToPassNew, addr) + let zkevmGasBefore := gas() + success := call(gasToPassNew, addr, value, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + + frameGasLeft := 0 + if gt(gasToPassNew, gasUsed) { + frameGasLeft := sub(gasToPassNew, gasUsed) + } + } + } + + function performCall(oldSp, evmGasLeft, isStatic) -> extraCost, sp { + let gasToPass,addr,value,argsOffset,argsSize,retOffset,retSize + + popStackCheck(oldSp, evmGasLeft, 7) + gasToPass, sp := popStackItemWithoutCheck(oldSp) + addr, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + argsOffset, sp := popStackItemWithoutCheck(sp) + argsSize, sp := popStackItemWithoutCheck(sp) + retOffset, sp := popStackItemWithoutCheck(sp) + retSize, sp := popStackItemWithoutCheck(sp) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + // static_gas = 0 + // dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + positive_value_cost + value_to_empty_account_cost + // code_execution_cost is the cost of the called code execution (limited by the gas parameter). + // If address is warm, then address_access_cost is 100, otherwise it is 2600. See section access sets. + // If value is not 0, then positive_value_cost is 9000. In this case there is also a call stipend that is given to make sure that a basic fallback function can be called. 2300 is thus removed from the cost, and also added to the gas input. + // If value is not 0 and the address given points to an empty account, then value_to_empty_account_cost is 25000. An account is empty if its balance is 0, its nonce is 0 and it has no code. + + extraCost := 0 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + extraCost := 2500 + } + + if gt(value, 0) { + extraCost := add(extraCost,6700) + gasToPass := add(gasToPass,2300) + } + + if and(isAddrEmpty(addr), gt(value, 0)) { + extraCost := add(extraCost,25000) + } + { + let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) + extraCost := add(extraCost,maxExpand) + } + gasToPass := capGas(evmGasLeft,gasToPass) + + argsOffset := add(argsOffset,MEM_OFFSET_INNER()) + retOffset := add(retOffset,MEM_OFFSET_INNER()) + + checkOverflow(argsOffset,argsSize, evmGasLeft) + checkOverflow(retOffset,retSize, evmGasLeft) + + checkMemOverflow(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflow(add(retOffset, retSize), evmGasLeft) + + let success, frameGasLeft + success, frameGasLeft, gasToPass:= _performCall( + addr, + gasToPass, + value, + argsOffset, + argsSize, + retOffset, + retSize, + isStatic + ) + + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) + sp := pushStackItem(sp,success, evmGasLeft) + } + + function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost { + let addr, gasToPass, argsOffset, argsSize, retOffset, retSize + + sp := oldSp + isStatic := oldIsStatic + + popStackCheck(sp, evmGasLeft, 6) + gasToPass, sp := popStackItemWithoutCheck(sp) + addr, sp := popStackItemWithoutCheck(sp) + argsOffset, sp := popStackItemWithoutCheck(sp) + argsSize, sp := popStackItemWithoutCheck(sp) + retOffset, sp := popStackItemWithoutCheck(sp) + retSize, sp := popStackItemWithoutCheck(sp) + + // addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + checkMultipleOverflow(argsOffset,argsSize,MEM_OFFSET_INNER(), evmGasLeft) + checkMultipleOverflow(retOffset, retSize,MEM_OFFSET_INNER(), evmGasLeft) + + checkMemOverflow(add(add(argsOffset, argsSize), MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflow(add(add(retOffset, retSize), MEM_OFFSET_INNER()), evmGasLeft) + + if iszero(_isEVM(addr)) { + revertWithGas(evmGasLeft) + } + + extraCost := 0 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + extraCost := 2500 + } + + { + let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) + extraCost := add(extraCost,maxExpand) + } + gasToPass := capGas(evmGasLeft,gasToPass) + + // TODO: Do this + // if warmAccount(addr) { + // extraCost = GAS_WARM_ACCESS; + // } else { + // extraCost = GAS_COLD_ACCOUNT_ACCESS; + // } + + _pushEVMFrame(gasToPass, isStatic) + let success := delegatecall( + // We can not just pass all gas here to prevert overflow of zkEVM gas counter + EVM_GAS_STIPEND(), + addr, + add(MEM_OFFSET_INNER(), argsOffset), + argsSize, + 0, + 0 + ) + + let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + + _popEVMFrame() + + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) + sp := pushStackItem(sp, success, evmGasLeft) + } + + function getMessageCallGas ( + _value, + _gas, + _gasLeft, + _memoryCost, + _extraGas + ) -> gasPlusExtra, gasPlusStipend { + let callStipend := 2300 + if iszero(_value) { + callStipend := 0 + } + + switch lt(_gasLeft, add(_extraGas, _memoryCost)) + case 0 + { + let _gasTemp := sub(sub(_gasLeft, _extraGas), _memoryCost) + // From the Tangerine Whistle fork, gas is capped at all but one 64th (remaining_gas / 64) + // of the remaining gas of the current context. If a call tries to send more, the gas is + // changed to match the maximum allowed. + let maxGasToPass := sub(_gasTemp, shr(6, _gasTemp)) // _gas >> 6 == _gas/64 + if gt(_gas, maxGasToPass) { + _gas := maxGasToPass + } + gasPlusExtra := add(_gas, _extraGas) + gasPlusStipend := add(_gas, callStipend) + } + default { + gasPlusExtra := add(_gas, _extraGas) + gasPlusStipend := add(_gas, callStipend) + } + } + + function _performStaticCall( + _calleeIsEVM, + _calleeGas, + _callee, + _inputOffset, + _inputLen, + _outputOffset, + _outputLen + ) -> success, _gasLeft { + if _calleeIsEVM { + _pushEVMFrame(_calleeGas, true) + // TODO Check the following comment from zkSync .sol. + // We can not just pass all gas here to prevert overflow of zkEVM gas counter + success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) + + _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) + _popEVMFrame() + } + + // zkEVM native + if iszero(_calleeIsEVM) { + _calleeGas := _getZkEVMGas(_calleeGas, _callee) + let zkevmGasBefore := gas() + success := staticcall(_calleeGas, _callee, _inputOffset, _inputLen, _outputOffset, _outputLen) + + _saveReturndataAfterZkEVMCall() + + let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + + _gasLeft := 0 + if gt(_calleeGas, gasUsed) { + _gasLeft := sub(_calleeGas, gasUsed) + } + } + } + + function isAddrEmpty(addr) -> isEmpty { + isEmpty := 0 + if iszero(extcodesize(addr)) { // YUL doesn't have short-circuit evaluation + if iszero(balance(addr)) { + if iszero(getRawNonce(addr)) { + isEmpty := 1 + } + } + } + } + + function _fetchConstructorReturnGas() -> gasLeft { + //selector is 0x24e5ab4a + + mstore8(0, 0x24) + mstore8(1, 0xe5) + mstore8(2, 0xab) + mstore8(3, 0x4a) + + let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + gasLeft := mload(0) + } + + function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeftOld) -> result, evmGasLeft { + pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) + + _eraseReturndataPointer() + + let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) + + if lt(selfbalance(),value) { + revertWithGas(evmGasLeftOld) + } + + offset := add(MEM_OFFSET_INNER(), offset) + + sp := pushStackItem(sp, mload(sub(offset, 0x80)), evmGasLeftOld) + sp := pushStackItem(sp, mload(sub(offset, 0x60)), evmGasLeftOld) + sp := pushStackItem(sp, mload(sub(offset, 0x40)), evmGasLeftOld) + sp := pushStackItem(sp, mload(sub(offset, 0x20)), evmGasLeftOld) + + // Selector + mstore(sub(offset, 0x80), 0x5b16a23c) + // Arg1: address + mstore(sub(offset, 0x60), addr) + // Arg2: init code + // Where the arg starts (third word) + mstore(sub(offset, 0x40), 0x40) + // Length of the init code + mstore(sub(offset, 0x20), size) + + _pushEVMFrame(gasForTheCall, false) + + result := call(INF_PASS_GAS(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 0) + + let gasLeft + switch result + case 0 { + gasLeft := _saveReturndataAfterEVMCall(0, 0) + } + default { + gasLeft := _fetchConstructorReturnGas() + } + + let gasUsed := sub(gasForTheCall, gasLeft) + evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) + + _popEVMFrame() + + switch result + case 1 { + incrementNonce(address()) + } + default { + switch isEOA(address()) + case 1 { + incrementNonce(address()) + } + default {} + } + + let back + + popStackCheck(sp, evmGasLeft, 4) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x20), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x40), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x60), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x80), back) + } + + function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { + evmGasLeft := chargeGas(evmGas, 100) + + let addr, dest, offset, len + popStackCheck(oldSp, evmGasLeft, 4) + addr, sp := popStackItemWithoutCheck(oldSp) + dest, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + len, sp := popStackItemWithoutCheck(sp) + + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost + // minimum_word_size = (size + 31) / 32 + + let dynamicGas := add( + mul(3, shr(5, add(len, 31))), + expandMemory(add(dest, len)) + ) + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + dynamicGas := add(dynamicGas, 2500) + } + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + let len_32 := shr(5, len) + for {let i := 0} lt(i, len_32) { i := add(i, 1) } { + mstore(add(dest,shl(5,i)),0) + } + let size_32 := shl(5,len_32) + let rest_32 := sub(len, size_32) + for {let i := 0} lt(i, rest_32) { i := add(i, 1) } { + mstore8(add(dest,add(size_32,i)),0) + } + + // Gets the code from the addr + if iszero(iszero(_getRawCodeHash(addr))) { + pop(_fetchDeployedCodeWithDest(addr, offset, len,add(dest,MEM_OFFSET_INNER()))) + } + + } + + function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { + evmGasLeft := chargeGas(evmGas, 32000) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let value, offset, size + + popStackCheck(oldSp, evmGasLeft, 3) + value, sp := popStackItemWithoutCheck(oldSp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) + + checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + + if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { + revertWithGas(evmGasLeft) + } + + if gt(value, balance(address())) { + revertWithGas(evmGasLeft) + } + + // dynamicGas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost + // minimum_word_size = (size + 31) / 32 + // init_code_cost = 2 * minimum_word_size + // code_deposit_cost = 200 * deployed_code_size + let dynamicGas := add( + shr(4, add(size, 31)), + expandMemory(add(offset, size)) + ) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + let addr := getNewAddress(address()) + + let result + result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + + switch result + case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } + default { sp := pushStackItem(sp, addr, evmGasLeft) } + } + + function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr{ + evmGasLeft := chargeGas(evmGas, 32000) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let value, offset, size, salt + + popStackCheck(oldSp, evmGasLeft, 4) + value, sp := popStackItemWithoutCheck(oldSp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + salt, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) + + checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + + if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { + revertWithGas(evmGasLeft) + } + + if gt(value, balance(address())) { + revertWithGas(evmGasLeft) + } + + // dynamicGas = init_code_cost + hash_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost + // minimum_word_size = (size + 31) / 32 + // init_code_cost = 2 * minimum_word_size + // hash_cost = 6 * minimum_word_size + // code_deposit_cost = 200 * deployed_code_size + evmGasLeft := chargeGas(evmGasLeft, add( + expandMemory(add(offset, size)), + shr(2, add(size, 31)) + )) + + { + let hashedBytecode := keccak256(add(MEM_OFFSET_INNER(), offset), size) + mstore8(0, 0xFF) + mstore(0x01, shl(0x60, address())) + mstore(0x15, salt) + mstore(0x35, hashedBytecode) + } + + addr := and( + keccak256(0, 0x55), + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + ) + + result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + } + + + function simulate( + isCallerEVM, + evmGasLeft, + isStatic, + ) -> returnOffset, returnLen, retGasLeft { + + returnOffset := MEM_OFFSET_INNER() + returnLen := 0 + + // stack pointer - index to first stack element; empty stack = -1 + let sp := sub(STACK_OFFSET(), 32) + // instruction pointer - index to next instruction. Not called pc because it's an + // actual yul/evm instruction. + let ip := add(BYTECODE_OFFSET(), 32) + let opcode + + let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) + + for { } true { } { + opcode := readIP(ip,maxAcceptablePos) + + switch opcode + case 0x00 { // OP_STOP + break + } + case 0x01 { // OP_ADD + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, add(a, b)) + ip := add(ip, 1) + } + case 0x02 { // OP_MUL + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, mul(a, b)) + ip := add(ip, 1) + } + case 0x03 { // OP_SUB + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sub(a, b)) + ip := add(ip, 1) + } + case 0x04 { // OP_DIV + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, div(a, b)) + ip := add(ip, 1) + } + case 0x05 { // OP_SDIV + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sdiv(a, b)) + ip := add(ip, 1) + } + case 0x06 { // OP_MOD + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, mod(a, b)) + ip := add(ip, 1) + } + case 0x07 { // OP_SMOD + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, smod(a, b)) + ip := add(ip, 1) + } + case 0x08 { // OP_ADDMOD + evmGasLeft := chargeGas(evmGasLeft, 8) + + let a, b, N + + popPushStackCheck(sp, evmGasLeft, 3) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + N, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, addmod(a, b, N)) + ip := add(ip, 1) + } + case 0x09 { // OP_MULMOD + evmGasLeft := chargeGas(evmGasLeft, 8) + + let a, b, N + + popStackCheck(sp, evmGasLeft, 3) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + N, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItem(sp, mulmod(a, b, N), evmGasLeft) + ip := add(ip, 1) + } + case 0x0A { // OP_EXP + evmGasLeft := chargeGas(evmGasLeft, 10) + + let a, exponent + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + exponent, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, exp(a, exponent)) + + let to_charge := 0 + for {} gt(exponent,0) {} { // while exponent > 0 + to_charge := add(to_charge, 50) + exponent := shr(8, exponent) + } + evmGasLeft := chargeGas(evmGasLeft, to_charge) + ip := add(ip, 1) + } + case 0x0B { // OP_SIGNEXTEND + evmGasLeft := chargeGas(evmGasLeft, 5) + + let b, x + + popPushStackCheck(sp, evmGasLeft, 2) + b, sp := popStackItemWithoutCheck(sp) + x, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, signextend(b, x)) + ip := add(ip, 1) + } + case 0x10 { // OP_LT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, lt(a, b)) + ip := add(ip, 1) + } + case 0x11 { // OP_GT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, gt(a, b)) + ip := add(ip, 1) + } + case 0x12 { // OP_SLT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, slt(a, b)) + ip := add(ip, 1) + } + case 0x13 { // OP_SGT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sgt(a, b)) + ip := add(ip, 1) + } + case 0x14 { // OP_EQ + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, eq(a, b)) + ip := add(ip, 1) + } + case 0x15 { // OP_ISZERO + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a + + popPushStackCheck(sp, evmGasLeft, 1) + a, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, iszero(a)) + ip := add(ip, 1) + } + case 0x16 { // OP_AND + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, and(a,b)) + ip := add(ip, 1) + } + case 0x17 { // OP_OR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, or(a,b)) + ip := add(ip, 1) + } + case 0x18 { // OP_XOR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, xor(a, b)) + ip := add(ip, 1) + } + case 0x19 { // OP_NOT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a + + popPushStackCheck(sp, evmGasLeft, 1) + a, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, not(a)) + ip := add(ip, 1) + } + case 0x1A { // OP_BYTE + evmGasLeft := chargeGas(evmGasLeft, 3) + + let i, x + + popPushStackCheck(sp, evmGasLeft, 2) + i, sp := popStackItemWithoutCheck(sp) + x, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, byte(i, x)) + ip := add(ip, 1) + } + case 0x1B { // OP_SHL + evmGasLeft := chargeGas(evmGasLeft, 3) + + let shift, value + + popPushStackCheck(sp, evmGasLeft, 2) + shift, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, shl(shift, value)) + ip := add(ip, 1) + } + case 0x1C { // OP_SHR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let shift, value + + popPushStackCheck(sp, evmGasLeft, 2) + shift, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, shr(shift, value)) + ip := add(ip, 1) + } + case 0x1D { // OP_SAR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let shift, value + + popPushStackCheck(sp, evmGasLeft, 2) + shift, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sar(shift, value)) + ip := add(ip, 1) + } + case 0x20 { // OP_KECCAK256 + evmGasLeft := chargeGas(evmGasLeft, 30) + + let offset, size + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) + checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + let keccak := keccak256(add(MEM_OFFSET_INNER(), offset), size) + + // When an offset is first accessed (either read or write), memory may trigger + // an expansion, which costs gas. + // dynamicGas = 6 * minimum_word_size + memory_expansion_cost + // minimum_word_size = (size + 31) / 32 + let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + sp := pushStackItem(sp, keccak, evmGasLeft) + ip := add(ip, 1) + } + case 0x30 { // OP_ADDRESS + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, address(), evmGasLeft) + ip := add(ip, 1) + } + case 0x31 { // OP_BALANCE + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr + + addr, sp := popStackItem(sp, evmGasLeft) + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + evmGasLeft := chargeGas(evmGasLeft, 2500) + } + + sp := pushStackItem(sp, balance(addr), evmGasLeft) + ip := add(ip, 1) + } + case 0x32 { // OP_ORIGIN + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, origin(), evmGasLeft) + ip := add(ip, 1) + } + case 0x33 { // OP_CALLER + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, caller(), evmGasLeft) + ip := add(ip, 1) + } + case 0x34 { // OP_CALLVALUE + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, callvalue(), evmGasLeft) + ip := add(ip, 1) + } + case 0x35 { // OP_CALLDATALOAD + evmGasLeft := chargeGas(evmGasLeft, 3) + + let i + + popPushStackCheck(sp, evmGasLeft, 1) + i, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, calldataload(i)) + ip := add(ip, 1) + } + case 0x36 { // OP_CALLDATASIZE + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, calldatasize(), evmGasLeft) + ip := add(ip, 1) + } + case 0x37 { // OP_CALLDATACOPY + evmGasLeft := chargeGas(evmGasLeft, 3) + + let destOffset, offset, size + + popStackCheck(sp, evmGasLeft, 3) + destOffset, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset,size,MEM_OFFSET_INNER(), evmGasLeft) + checkMultipleOverflow(destOffset,size,MEM_OFFSET_INNER(), evmGasLeft) + + if or(gt(add(add(offset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM()), gt(add(add(destOffset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM())) { + for { let i := 0 } lt(i, size) { i := add(i, 1) } { + mstore8( + add(add(destOffset, MEM_OFFSET_INNER()), i), + 0 + ) + } + } + + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + // minimum_word_size = (size + 31) / 32 + let dynamicGas := add(mul(3, shr(5, add(size, 31))), expandMemory(add(destOffset, size))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + calldatacopy(add(destOffset, MEM_OFFSET_INNER()), offset, size) + ip := add(ip, 1) + + } + case 0x38 { // OP_CODESIZE + evmGasLeft := chargeGas(evmGasLeft, 2) + + let bytecodeLen := mload(BYTECODE_OFFSET()) + sp := pushStackItem(sp, bytecodeLen, evmGasLeft) + ip := add(ip, 1) + } + case 0x39 { // OP_CODECOPY + + evmGasLeft := chargeGas(evmGasLeft, 3) + + let dst, offset, len + + popStackCheck(sp, evmGasLeft, 3) + dst, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + len, sp := popStackItemWithoutCheck(sp) + + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + // minimum_word_size = (size + 31) / 32 + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dst, len))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + dst := add(dst, MEM_OFFSET_INNER()) + offset := add(add(offset, BYTECODE_OFFSET()), 32) + + checkOverflow(dst,len, evmGasLeft) + checkMemOverflow(add(dst, len), evmGasLeft) + // Check bytecode overflow + if gt(add(offset, len), sub(MEM_OFFSET(), 1)) { + revertWithGas(evmGasLeft) + } + + for { let i := 0 } lt(i, len) { i := add(i, 1) } { + mstore8( + add(dst, i), + shr(248, mload(add(offset, i))) + ) + } + ip := add(ip, 1) + } + case 0x3A { // OP_GASPRICE + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, gasprice(), evmGasLeft) + ip := add(ip, 1) + } + case 0x3B { // OP_EXTCODESIZE + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr + addr, sp := popStackItem(sp, evmGasLeft) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + evmGasLeft := chargeGas(evmGasLeft, 2500) + } + + // TODO: check, the .sol uses extcodesize directly, but it doesnt seem to work + // if a contract is created it works, but if the address is a zkSync's contract + // what happens? + // sp := pushStackItem(sp, extcodesize(addr), evmGasLeft) + + switch _isEVM(addr) + case 0 { sp := pushStackItem(sp, extcodesize(addr), evmGasLeft) } + default { sp := pushStackItem(sp, _fetchDeployedCodeLen(addr), evmGasLeft) } + ip := add(ip, 1) + } + case 0x3C { // OP_EXTCODECOPY + evmGasLeft, sp := performExtCodeCopy(evmGasLeft, sp) + ip := add(ip, 1) + } + case 0x3D { // OP_RETURNDATASIZE + evmGasLeft := chargeGas(evmGasLeft, 2) + + let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) + sp := pushStackItem(sp, rdz, evmGasLeft) + ip := add(ip, 1) + } + case 0x3E { // OP_RETURNDATACOPY + evmGasLeft := chargeGas(evmGasLeft, 3) + + let dest, offset, len + popStackCheck(sp, evmGasLeft, 3) + dest, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + len, sp := popStackItemWithoutCheck(sp) + + // TODO: check if these conditions are met + // The addition offset + size overflows. + // offset + size is larger than RETURNDATASIZE. + checkOverflow(offset,len, evmGasLeft) + if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + // minimum_word_size = (size + 31) / 32 + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dest, len))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + copyActivePtrData(add(MEM_OFFSET_INNER(), dest), offset, len) + ip := add(ip, 1) + } + case 0x3F { // OP_EXTCODEHASH + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr + addr, sp := popStackItem(sp, evmGasLeft) + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + evmGasLeft := chargeGas(evmGasLeft, 2500) + } + + ip := add(ip, 1) + if iszero(addr) { + sp := pushStackItem(sp, 0, evmGasLeft) + continue + } + sp := pushStackItem(sp, extcodehash(addr), evmGasLeft) + } + case 0x40 { // OP_BLOCKHASH + evmGasLeft := chargeGas(evmGasLeft, 20) + + let blockNumber + popPushStackCheck(sp, evmGasLeft, 1) + blockNumber, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, blockhash(blockNumber)) + ip := add(ip, 1) + } + case 0x41 { // OP_COINBASE + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, coinbase(), evmGasLeft) + ip := add(ip, 1) + } + case 0x42 { // OP_TIMESTAMP + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, timestamp(), evmGasLeft) + ip := add(ip, 1) + } + case 0x43 { // OP_NUMBER + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, number(), evmGasLeft) + ip := add(ip, 1) + } + case 0x44 { // OP_PREVRANDAO + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, prevrandao(), evmGasLeft) + ip := add(ip, 1) + } + case 0x45 { // OP_GASLIMIT + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, gaslimit(), evmGasLeft) + ip := add(ip, 1) + } + case 0x46 { // OP_CHAINID + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, chainid(), evmGasLeft) + ip := add(ip, 1) + } + case 0x47 { // OP_SELFBALANCE + evmGasLeft := chargeGas(evmGasLeft, 5) + sp := pushStackItem(sp, selfbalance(), evmGasLeft) + ip := add(ip, 1) + } + case 0x48 { // OP_BASEFEE + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, basefee(), evmGasLeft) + ip := add(ip, 1) + } + case 0x50 { // OP_POP + evmGasLeft := chargeGas(evmGasLeft, 2) + + let _y + + _y, sp := popStackItem(sp, evmGasLeft) + ip := add(ip, 1) + } + case 0x51 { // OP_MLOAD + evmGasLeft := chargeGas(evmGasLeft, 3) + + let offset + + offset, sp := popStackItem(sp, evmGasLeft) + + checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + let expansionGas := expandMemory(add(offset, 32)) + evmGasLeft := chargeGas(evmGasLeft, expansionGas) + + checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + let memValue := mload(add(MEM_OFFSET_INNER(), offset)) + sp := pushStackItem(sp, memValue, evmGasLeft) + ip := add(ip, 1) + } + case 0x52 { // OP_MSTORE + evmGasLeft := chargeGas(evmGasLeft, 3) + + let offset, value + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + let expansionGas := expandMemory(add(offset, 32)) + evmGasLeft := chargeGas(evmGasLeft, expansionGas) + + checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + mstore(add(MEM_OFFSET_INNER(), offset), value) + ip := add(ip, 1) + } + case 0x53 { // OP_MSTORE8 + evmGasLeft := chargeGas(evmGasLeft, 3) + + let offset, value + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + let expansionGas := expandMemory(add(offset, 1)) + evmGasLeft := chargeGas(evmGasLeft, expansionGas) + + checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + mstore8(add(MEM_OFFSET_INNER(), offset), value) + ip := add(ip, 1) + } + case 0x54 { // OP_SLOAD + + evmGasLeft := chargeGas(evmGasLeft, 100) + + let key, value, isWarm + + key, sp := popStackItem(sp, evmGasLeft) + + let wasWarm := isSlotWarm(key) + + if iszero(wasWarm) { + evmGasLeft := chargeGas(evmGasLeft, 2000) + } + + value := sload(key) + + if iszero(wasWarm) { + let _wasW, _orgV := warmSlot(key, value) + } + + sp := pushStackItem(sp,value, evmGasLeft) + ip := add(ip, 1) + } + case 0x55 { // OP_SSTORE + evmGasLeft := chargeGas(evmGasLeft, 100) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let key, value, gasSpent + + popStackCheck(sp, evmGasLeft, 2) + key, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + ip := add(ip, 1) + { + // Here it is okay to read before we charge since we known anyway that + // the context has enough funds to compensate at least for the read. + // Im not sure if we need this before: require(gasLeft > GAS_CALL_STIPEND); + let currentValue := sload(key) + let wasWarm, originalValue := warmSlot(key, currentValue) + + if eq(value, currentValue) { + continue + } + + if eq(originalValue, currentValue) { + gasSpent := 19900 + if originalValue { + gasSpent := 2800 + } + } + + if iszero(wasWarm) { + gasSpent := add(gasSpent, 2100) + } + } + + evmGasLeft := chargeGas(evmGasLeft, gasSpent) + sstore(key, value) + + } + // NOTE: We don't currently do full jumpdest validation + // (i.e. validating a jumpdest isn't in PUSH data) + case 0x56 { // OP_JUMP + evmGasLeft := chargeGas(evmGasLeft, 8) + + let counter + + counter, sp := popStackItem(sp, evmGasLeft) + + ip := add(add(BYTECODE_OFFSET(), 32), counter) + + // Check next opcode is JUMPDEST + let nextOpcode := readIP(ip,maxAcceptablePos) + if iszero(eq(nextOpcode, 0x5B)) { + revertWithGas(evmGasLeft) + } + } + case 0x57 { // OP_JUMPI + evmGasLeft := chargeGas(evmGasLeft, 10) + + let counter, b + + popStackCheck(sp, evmGasLeft, 2) + counter, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + if iszero(b) { + ip := add(ip, 1) + continue + } + + ip := add(add(BYTECODE_OFFSET(), 32), counter) + + // Check next opcode is JUMPDEST + let nextOpcode := readIP(ip,maxAcceptablePos) + if iszero(eq(nextOpcode, 0x5B)) { + revertWithGas(evmGasLeft) + } + } + case 0x58 { // OP_PC + evmGasLeft := chargeGas(evmGasLeft, 2) + ip := add(ip, 1) + + // PC = ip - 32 (bytecode size) - 1 (current instruction) + sp := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft) + } + case 0x59 { // OP_MSIZE + evmGasLeft := chargeGas(evmGasLeft,2) + + let size + + size := mload(MEM_OFFSET()) + size := shl(5,size) + sp := pushStackItem(sp,size, evmGasLeft) + ip := add(ip, 1) + } + case 0x5A { // OP_GAS + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, evmGasLeft, evmGasLeft) + ip := add(ip, 1) + } + case 0x5B { // OP_JUMPDEST + evmGasLeft := chargeGas(evmGasLeft, 1) + ip := add(ip, 1) + } + case 0x5C { // OP_TLOAD + evmGasLeft := chargeGas(evmGasLeft, 100) + + let key + popPushStackCheck(sp, evmGasLeft, 1) + key, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, tload(key)) + ip := add(ip, 1) + } + case 0x5D { // OP_TSTORE + evmGasLeft := chargeGas(evmGasLeft, 100) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let key, value + popStackCheck(sp, evmGasLeft, 2) + key, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + tstore(key, value) + ip := add(ip, 1) + } + case 0x5E { // OP_MCOPY + let destOffset, offset, size + popStackCheck(sp, evmGasLeft, 3) + destOffset, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + expandMemory(add(destOffset, size)) + expandMemory(add(offset, size)) + + let oldSize := mul(mload(MEM_OFFSET()),32) + if gt(add(oldSize,size),MAX_POSSIBLE_MEM()) { + revertWithGas(evmGasLeft) + } + + for { let i := 0 } lt(i, size) { i := add(i, 1) } { + mstore8( + add(add(oldSize,MEM_OFFSET_INNER()), i), + shr(248,mload(add(add(offset,MEM_OFFSET_INNER()), i))) + ) + } + for { let i := 0 } lt(i, size) { i := add(i, 1) } { + mstore8( + add(add(destOffset,MEM_OFFSET_INNER()), i), + shr(248,mload(add(add(oldSize,MEM_OFFSET_INNER()), i))) + ) + } + ip := add(ip, 1) + } + case 0x5F { // OP_PUSH0 + evmGasLeft := chargeGas(evmGasLeft, 2) + + let value := 0 + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 1) + } + case 0x60 { // OP_PUSH1 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,1) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 1) + } + case 0x61 { // OP_PUSH2 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,2) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 2) + } + case 0x62 { // OP_PUSH3 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,3) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 3) + } + case 0x63 { // OP_PUSH4 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,4) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 4) + } + case 0x64 { // OP_PUSH5 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,5) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 5) + } + case 0x65 { // OP_PUSH6 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,6) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 6) + } + case 0x66 { // OP_PUSH7 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,7) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 7) + } + case 0x67 { // OP_PUSH8 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,8) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 8) + } + case 0x68 { // OP_PUSH9 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,9) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 9) + } + case 0x69 { // OP_PUSH10 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,10) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 10) + } + case 0x6A { // OP_PUSH11 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,11) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 11) + } + case 0x6B { // OP_PUSH12 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,12) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 12) + } + case 0x6C { // OP_PUSH13 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,13) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 13) + } + case 0x6D { // OP_PUSH14 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,14) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 14) + } + case 0x6E { // OP_PUSH15 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,15) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 15) + } + case 0x6F { // OP_PUSH16 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,16) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 16) + } + case 0x70 { // OP_PUSH17 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,17) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 17) + } + case 0x71 { // OP_PUSH18 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,18) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 18) + } + case 0x72 { // OP_PUSH19 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,19) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 19) + } + case 0x73 { // OP_PUSH20 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,20) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 20) + } + case 0x74 { // OP_PUSH21 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,21) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 21) + } + case 0x75 { // OP_PUSH22 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,22) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 22) + } + case 0x76 { // OP_PUSH23 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,23) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 23) + } + case 0x77 { // OP_PUSH24 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,24) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 24) + } + case 0x78 { // OP_PUSH25 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,25) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 25) + } + case 0x79 { // OP_PUSH26 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,26) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 26) + } + case 0x7A { // OP_PUSH27 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,27) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 27) + } + case 0x7B { // OP_PUSH28 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,28) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 28) + } + case 0x7C { // OP_PUSH29 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,29) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 29) + } + case 0x7D { // OP_PUSH30 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,30) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 30) + } + case 0x7E { // OP_PUSH31 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,31) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 31) + } + case 0x7F { // OP_PUSH32 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,32) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 32) + } + case 0x80 { // OP_DUP1 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 1) + ip := add(ip, 1) + } + case 0x81 { // OP_DUP2 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 2) + ip := add(ip, 1) + } + case 0x82 { // OP_DUP3 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 3) + ip := add(ip, 1) + } + case 0x83 { // OP_DUP4 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 4) + ip := add(ip, 1) + } + case 0x84 { // OP_DUP5 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 5) + ip := add(ip, 1) + } + case 0x85 { // OP_DUP6 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 6) + ip := add(ip, 1) + } + case 0x86 { // OP_DUP7 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 7) + ip := add(ip, 1) + } + case 0x87 { // OP_DUP8 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 8) + ip := add(ip, 1) + } + case 0x88 { // OP_DUP9 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 9) + ip := add(ip, 1) + } + case 0x89 { // OP_DUP10 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 10) + ip := add(ip, 1) + } + case 0x8A { // OP_DUP11 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 11) + ip := add(ip, 1) + } + case 0x8B { // OP_DUP12 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 12) + ip := add(ip, 1) + } + case 0x8C { // OP_DUP13 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 13) + ip := add(ip, 1) + } + case 0x8D { // OP_DUP14 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 14) + ip := add(ip, 1) + } + case 0x8E { // OP_DUP15 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 15) + ip := add(ip, 1) + } + case 0x8F { // OP_DUP16 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 16) + ip := add(ip, 1) + } + case 0x90 { // OP_SWAP1 + evmGasLeft := swapStackItem(sp, evmGasLeft, 1) + ip := add(ip, 1) + } + case 0x91 { // OP_SWAP2 + evmGasLeft := swapStackItem(sp, evmGasLeft, 2) + ip := add(ip, 1) + } + case 0x92 { // OP_SWAP3 + evmGasLeft := swapStackItem(sp, evmGasLeft, 3) + ip := add(ip, 1) + } + case 0x93 { // OP_SWAP4 + evmGasLeft := swapStackItem(sp, evmGasLeft, 4) + ip := add(ip, 1) + } + case 0x94 { // OP_SWAP5 + evmGasLeft := swapStackItem(sp, evmGasLeft, 5) + ip := add(ip, 1) + } + case 0x95 { // OP_SWAP6 + evmGasLeft := swapStackItem(sp, evmGasLeft, 6) + ip := add(ip, 1) + } + case 0x96 { // OP_SWAP7 + evmGasLeft := swapStackItem(sp, evmGasLeft, 7) + ip := add(ip, 1) + } + case 0x97 { // OP_SWAP8 + evmGasLeft := swapStackItem(sp, evmGasLeft, 8) + ip := add(ip, 1) + } + case 0x98 { // OP_SWAP9 + evmGasLeft := swapStackItem(sp, evmGasLeft, 9) + ip := add(ip, 1) + } + case 0x99 { // OP_SWAP10 + evmGasLeft := swapStackItem(sp, evmGasLeft, 10) + ip := add(ip, 1) + } + case 0x9A { // OP_SWAP11 + evmGasLeft := swapStackItem(sp, evmGasLeft, 11) + ip := add(ip, 1) + } + case 0x9B { // OP_SWAP12 + evmGasLeft := swapStackItem(sp, evmGasLeft, 12) + ip := add(ip, 1) + } + case 0x9C { // OP_SWAP13 + evmGasLeft := swapStackItem(sp, evmGasLeft, 13) + ip := add(ip, 1) + } + case 0x9D { // OP_SWAP14 + evmGasLeft := swapStackItem(sp, evmGasLeft, 14) + ip := add(ip, 1) + } + case 0x9E { // OP_SWAP15 + evmGasLeft := swapStackItem(sp, evmGasLeft, 15) + ip := add(ip, 1) + } + case 0x9F { // OP_SWAP16 + evmGasLeft := swapStackItem(sp, evmGasLeft, 16) + ip := add(ip, 1) + } + case 0xA0 { // OP_LOG0 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) + checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + log0(add(offset, MEM_OFFSET_INNER()), size) + ip := add(ip, 1) + } + case 0xA1 { // OP_LOG1 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size, topic1 + popStackCheck(sp, evmGasLeft, 3) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + topic1, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) + checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 375) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + ip := add(ip, 1) + } + case 0xA2 { // OP_LOG2 + evmGasLeft := chargeGas(evmGasLeft, 375) + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) + checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 750) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + { + let topic1, topic2 + popStackCheck(sp, evmGasLeft, 2) + topic1, sp := popStackItemWithoutCheck(sp) + topic2, sp := popStackItemWithoutCheck(sp) + log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) + } + ip := add(ip, 1) + } + case 0xA3 { // OP_LOG3 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) + + checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 1125) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + { + let topic1, topic2, topic3 + popStackCheck(sp, evmGasLeft, 3) + topic1, sp := popStackItemWithoutCheck(sp) + topic2, sp := popStackItemWithoutCheck(sp) + topic3, sp := popStackItemWithoutCheck(sp) + log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) + } + ip := add(ip, 1) + } + case 0xA4 { // OP_LOG4 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) + checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 1500) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + { + let topic1, topic2, topic3, topic4 + popStackCheck(sp, evmGasLeft, 4) + topic1, sp := popStackItemWithoutCheck(sp) + topic2, sp := popStackItemWithoutCheck(sp) + topic3, sp := popStackItemWithoutCheck(sp) + topic4, sp := popStackItemWithoutCheck(sp) + log4(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3, topic4) + } + ip := add(ip, 1) + } + case 0xF0 { // OP_CREATE + evmGasLeft, sp := performCreate(evmGasLeft, sp, isStatic) + ip := add(ip, 1) + } + case 0xF1 { // OP_CALL + evmGasLeft := chargeGas(evmGasLeft, 100) + + let gasUsed + + // A function was implemented in order to avoid stack depth errors. + gasUsed, sp := performCall(sp, evmGasLeft, isStatic) + + // Check if the following is ok + evmGasLeft := chargeGas(evmGasLeft, gasUsed) + ip := add(ip, 1) + } + case 0xF3 { // OP_RETURN + let offset,size + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset,size, evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + + returnLen := size + checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + returnOffset := add(MEM_OFFSET_INNER(), offset) + break + } + case 0xF4 { // OP_DELEGATECALL + evmGasLeft := chargeGas(evmGasLeft, 100) + + let gasUsed + sp, isStatic, gasUsed := delegateCall(sp, isStatic, evmGasLeft) + + evmGasLeft := chargeGas(evmGasLeft, gasUsed) + ip := add(ip, 1) + } + case 0xF5 { // OP_CREATE2 + let result, addr + evmGasLeft, sp, result, addr := performCreate2(evmGasLeft, sp, isStatic) + switch result + case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } + default { sp := pushStackItem(sp, addr, evmGasLeft) } + ip := add(ip, 1) + } + case 0xFA { // OP_STATICCALL + evmGasLeft := chargeGas(evmGasLeft, 100) + + let gasUsed + gasUsed, sp := performStaticCall(sp,evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft,gasUsed) + ip := add(ip, 1) + } + case 0xFD { // OP_REVERT + let offset,size + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + ensureAcceptableMemLocation(offset) + ensureAcceptableMemLocation(size) + evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + + offset := add(offset, MEM_OFFSET_INNER()) + offset,size := addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) + + revert(offset,size) + } + case 0xFE { // OP_INVALID + evmGasLeft := 0 + + revertWithGas(evmGasLeft) + } + default { + printString("INVALID OPCODE") + printHex(opcode) + revert(0, 0) + } + } + + + retGasLeft := evmGasLeft + } + + //////////////////////////////////////////////////////////////// + // FALLBACK + //////////////////////////////////////////////////////////////// + + let evmGasLeft, isStatic, isCallerEVM := consumeEvmFrame() + + if isStatic { + revert(0, 0) + } + + getConstructorBytecode() + + if iszero(isCallerEVM) { + evmGasLeft := getEVMGas() + } + + let offset, len, gasToReturn := simulate(isCallerEVM, evmGasLeft, false) + + gasToReturn := validateCorrectBytecode(offset, len, gasToReturn) + + offset, len := padBytecode(offset, len) + + setDeployedCode(gasToReturn, offset, len) + } + object "EVMInterpreter_deployed" { + code { + function SYSTEM_CONTRACTS_OFFSET() -> offset { + offset := 0x8000 + } + + function ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008002 + } + + function NONCE_HOLDER_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008003 + } + + function DEPLOYER_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008006 + } + + function CODE_ADDRESS_CALL_ADDRESS() -> addr { + addr := 0x000000000000000000000000000000000000FFFE + } + + function CODE_ORACLE_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008012 + } + + function EVM_GAS_MANAGER_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008013 + } + + function CALLFLAGS_CALL_ADDRESS() -> addr { + addr := 0x000000000000000000000000000000000000FFEF + } + + function DEBUG_SLOT_OFFSET() -> offset { + offset := mul(32, 32) + } + + function LAST_RETURNDATA_SIZE_OFFSET() -> offset { + offset := add(DEBUG_SLOT_OFFSET(), mul(5, 32)) + } + + function STACK_OFFSET() -> offset { + offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 32) + } + + function BYTECODE_OFFSET() -> offset { + offset := add(STACK_OFFSET(), mul(1024, 32)) + } + + function INF_PASS_GAS() -> inf { + inf := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + } + + function MAX_POSSIBLE_BYTECODE() -> max { + max := 32000 + } + + function MEM_OFFSET() -> offset { + offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_BYTECODE()) + } + + function MEM_OFFSET_INNER() -> offset { + offset := add(MEM_OFFSET(), 32) + } + + function MAX_POSSIBLE_MEM() -> max { + max := 0x100000 // 1MB + } + + function MAX_MEMORY_FRAME() -> max { + max := add(MEM_OFFSET_INNER(), MAX_POSSIBLE_MEM()) + } + + function MAX_UINT() -> max_uint { + max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + } + + // It is the responsibility of the caller to ensure that ip >= BYTECODE_OFFSET + 32 + function readIP(ip,maxAcceptablePos) -> opcode { + // TODO: Why not do this at the beginning once instead of every time? + if gt(ip, maxAcceptablePos) { + revert(0, 0) + } + + opcode := and(mload(sub(ip, 31)), 0xff) + } + + function readBytes(start, maxAcceptablePos,length) -> value { + if gt(add(start,sub(length,1)), maxAcceptablePos) { + revert(0, 0) + } + value := shr(mul(8,sub(32,length)),mload(start)) + } + + function dupStackItem(sp, evmGas, position) -> newSp, evmGasLeft { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, sub(position, 1))) + + if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + let dup := mload(tempSp) + + newSp := add(sp, 0x20) + mstore(newSp, dup) + } + + function swapStackItem(sp, evmGas, position) -> evmGasLeft { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, position)) + + if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + + let s2 := mload(sp) + let s1 := mload(tempSp) + + mstore(sp, s1) + mstore(tempSp, s2) + } + + function popStackItem(sp, evmGasLeft) -> a, newSp { + // We can not return any error here, because it would break compatibility + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + a := mload(sp) + newSp := sub(sp, 0x20) + } + + function pushStackItem(sp, item, evmGasLeft) -> newSp { + if or(gt(sp, BYTECODE_OFFSET()), eq(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + newSp := add(sp, 0x20) + mstore(newSp, item) + } + + function popStackItemWithoutCheck(sp) -> a, newSp { + a := mload(sp) + newSp := sub(sp, 0x20) + } + + function pushStackItemWithoutCheck(sp, item) -> newSp { + newSp := add(sp, 0x20) + mstore(newSp, item) + } + + function popStackCheck(sp, evmGasLeft, numInputs) { + if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + } + + function popPushStackCheck(sp, evmGasLeft, numInputs) { + let popCheck := lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) + let pushOffset := sub(sp, mul(0x20, numInputs)) + let pushCheck := or(gt(pushOffset, BYTECODE_OFFSET()), eq(pushOffset, BYTECODE_OFFSET())) + if or(popCheck, pushCheck) { + revertWithGas(evmGasLeft) + } + } + + function getCodeAddress() -> addr { + addr := verbatim_0i_1o("code_source") + } + + function loadReturndataIntoActivePtr() { + verbatim_0i_0o("return_data_ptr_to_active") + } + + function loadCalldataIntoActivePtr() { + verbatim_0i_0o("calldata_ptr_to_active") + } + + function getActivePtrDataSize() -> size { + size := verbatim_0i_1o("active_ptr_data_size") + } + + function copyActivePtrData(_dest, _source, _size) { + verbatim_3i_0o("active_ptr_data_copy", _dest, _source, _size) + } + + function ptrAddIntoActive(_dest) { + verbatim_1i_0o("active_ptr_add_assign", _dest) + } + + function ptrShrinkIntoActive(_dest) { + verbatim_1i_0o("active_ptr_shrink_assign", _dest) + } + + function _getRawCodeHash(account) -> hash { + // TODO: Unhardcode this selector + mstore8(0, 0x4d) + mstore8(1, 0xe2) + mstore8(2, 0xe4) + mstore8(3, 0x68) + mstore(4, account) + + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + hash := mload(0) + } + + function _getCodeHash(account) -> hash { + // function getCodeHash(uint256 _input) external view override returns (bytes32) + // 0xe03fe177 + // TODO: Unhardcode this selector + mstore8(0, 0xe0) + mstore8(1, 0x3f) + mstore8(2, 0xe1) + mstore8(3, 0x77) + mstore(4, account) + + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + hash := mload(0) + } + + function getIsStaticFromCallFlags() -> isStatic { + isStatic := verbatim_0i_1o("get_global::call_flags") + // TODO: make it a constnat + isStatic := iszero(iszero(and(isStatic, 0x04))) + } + + // Basically performs an extcodecopy, while returning the length of the bytecode. + function _fetchDeployedCode(addr, _offset, _len) -> codeLen { + codeLen := _fetchDeployedCodeWithDest(addr, 0, _len, _offset) + } + + // Basically performs an extcodecopy, while returning the length of the bytecode. + function _fetchDeployedCodeWithDest(addr, _offset, _len, dest) -> codeLen { + let codeHash := _getRawCodeHash(addr) + + mstore(0, codeHash) + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + // The first word is the true length of the bytecode + returndatacopy(0, 0, 32) + codeLen := mload(0) + + if gt(_len, codeLen) { + _len := codeLen + } + + returndatacopy(dest, add(32,_offset), _len) + } + + // Returns the length of the bytecode. + function _fetchDeployedCodeLen(addr) -> codeLen { + let codeHash := _getRawCodeHash(addr) + + mstore(0, codeHash) + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + + switch iszero(success) + case 1 { + // The code oracle call can only fail in the case where the contract + // we are querying is the current one executing and it has not yet been + // deployed, i.e., if someone calls codesize (or extcodesize(address())) + // inside the constructor. In that case, code length is zero. + codeLen := 0 + } + default { + // The first word is the true length of the bytecode + returndatacopy(0, 0, 32) + codeLen := mload(0) + } + + } + + function getDeployedBytecode() { + let codeLen := _fetchDeployedCode( + getCodeAddress(), + add(BYTECODE_OFFSET(), 32), + MAX_POSSIBLE_BYTECODE() + ) + + mstore(BYTECODE_OFFSET(), codeLen) + } + + function consumeEvmFrame() -> passGas, isStatic, callerEVM { + // function consumeEvmFrame() external returns (uint256 passGas, bool isStatic) + // TODO: Unhardcode selector + mstore8(0, 0x04) + mstore8(1, 0xc1) + mstore8(2, 0x4e) + mstore8(3, 0x9e) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 4, 0, 64) + + if iszero(success) { + // Should never happen + revert(0, 0) + } + + passGas := mload(0) + isStatic := mload(32) + + if iszero(eq(passGas, INF_PASS_GAS())) { + callerEVM := true + } + } + + function chargeGas(prevGas, toCharge) -> gasRemaining { + if lt(prevGas, toCharge) { + revertWithGas(0) + } + + gasRemaining := sub(prevGas, toCharge) + } + + function getMax(a, b) -> max { + max := b + if gt(a, b) { + max := a + } + } + + function getMin(a, b) -> min { + min := b + if lt(a, b) { + min := a + } + } + + function bitLength(n) -> bitLen { + for { } gt(n, 0) { } { // while(n > 0) + if iszero(n) { + bitLen := 1 + break + } + n := shr(1, n) + bitLen := add(bitLen, 1) + } + } + + function bitMaskFromBytes(nBytes) -> bitMask { + bitMask := sub(exp(2, mul(nBytes, 8)), 1) // 2**(nBytes*8) - 1 + } + // The gas cost mentioned here is purely the cost of the contract, + // and does not consider the cost of the call itself nor the instructions + // to put the parameters in memory. + // Take into account MEM_OFFSET_INNER() when passing the argsOfsset + function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { + switch addr + case 0x01 { // ecRecover + gasToCharge := 3000 + } + case 0x02 { // SHA2-256 + gasToCharge := 60 + let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 + gasToCharge := add(gasToCharge, mul(12, dataWordSize)) + } + case 0x03 { // RIPEMD-160 + gasToCharge := 600 + let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 + gasToCharge := add(gasToCharge, mul(120, dataWordSize)) + } + case 0x04 { // identity + gasToCharge := 15 + let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 + gasToCharge := add(gasToCharge, mul(3, dataWordSize)) + } + // [0; 31] (32 bytes) Bsize Byte size of B + // [32; 63] (32 bytes) Esize Byte size of E + // [64; 95] (32 bytes) Msize Byte size of M + /* + def calculate_iteration_count(exponent_length, exponent): + iteration_count = 0 + if exponent_length <= 32 and exponent == 0: iteration_count = 0 + elif exponent_length <= 32: iteration_count = exponent.bit_length() - 1 + elif exponent_length > 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1) + return max(iteration_count, 1) + def calculate_gas_cost(base_length, modulus_length, exponent_length, exponent): + multiplication_complexity = calculate_multiplication_complexity(base_length, modulus_length) + iteration_count = calculate_iteration_count(exponent_length, exponent) + return max(200, math.floor(multiplication_complexity * iteration_count / 3)) + */ + // modexp gas cost EIP below + // https://eips.ethereum.org/EIPS/eip-2565 + case 0x05 { // modexp + let mulComplex + let Bsize := mload(argsOffset) + let Esize := mload(add(argsOffset, 0x20)) + + { + let words := getMax(Bsize, mload(add(argsOffset, 0x40))) // shr(3, x) == x/8 + if and(lt(words, 64), eq(words, 64)){ + // if x <= 64: return x ** 2 + mulComplex := mul(words, words) + } + if and(and(lt(words, 1024), eq(words, 1024)), gt(words, 64)){ + // elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072 + mulComplex := sub(add(shr(2, mul(words, words)), mul(96, words)), 3072) + } + if gt(words, 64) { + // else: return x ** 2 // 16 + 480 * x - 199680 + mulComplex := sub(add(shr(4, mul(words, words)), mul(480, words)), 199680) + } + } + + // [96 + Bsize; 96 + Bsize + Esize] E + let exponentFirst256, exponentIsZero, exponentBitLen + if or(lt(Esize, 32), eq(Esize, 32)) { + // Maybe there isn't exactly 32 bytes, so a mask should be applied + exponentFirst256 := mload(add(add(argsOffset, 0x60), Bsize)) + exponentBitLen := bitLength(exponentFirst256) + exponentIsZero := iszero(and(exponentFirst256, bitMaskFromBytes(Esize))) + } + if gt(Esize, 32) { + exponentFirst256 := mload(add(add(argsOffset, 0x60), Bsize)) + exponentIsZero := iszero(exponentFirst256) + let exponentNext + // This is done because the first 32bytes of the exponent were loaded + for { let i := 0 } lt(i, div(Esize, 32)) { i := add(i, 1) Esize := sub(Esize, 32) } { // check every 32bytes + // Maybe there isn't exactly 32 bytes, so a mask should be applied + exponentNext := mload(add(add(add(argsOffset, 0x60), Bsize), add(mul(i, 32), 32))) + exponentBitLen := add(bitLength(exponentNext), mul(mul(32, 8), add(i, 1))) + if iszero(iszero(and(exponentNext, bitMaskFromBytes(Esize)))) { + exponentIsZero := false + } + } + } + + // if exponent_length <= 32 and exponent == 0: iteration_count = 0 + // return max(iteration_count, 1) + let iterationCount := 1 + // elif exponent_length <= 32: iteration_count = exponent.bit_length() - 1 + if and(lt(Esize, 32), iszero(exponentIsZero)) { + iterationCount := sub(exponentBitLen, 1) + } + // elif exponent_length > 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1) + if gt(Esize, 32) { + iterationCount := add(mul(8, sub(Esize, 32)), sub(bitLength(and(exponentFirst256, MAX_UINT())), 1)) + } + + gasToCharge := getMax(200, div(mul(mulComplex, iterationCount), 3)) + } + // ecAdd ecMul ecPairing EIP below + // https://eips.ethereum.org/EIPS/eip-1108 + case 0x06 { // ecAdd + // The gas cost is fixed at 150. However, if the input + // does not allow to compute a valid result, all the gas sent is consumed. + gasToCharge := 150 + } + case 0x07 { // ecMul + // The gas cost is fixed at 6000. However, if the input + // does not allow to compute a valid result, all the gas sent is consumed. + gasToCharge := 6000 + } + // 35,000 * k + 45,000 gas, where k is the number of pairings being computed. + // The input must always be a multiple of 6 32-byte values. + case 0x08 { // ecPairing + gasToCharge := 45000 + let k := div(argsSize, 0xC0) // 0xC0 == 6*32 + gasToCharge := add(gasToCharge, mul(k, 35000)) + } + case 0x09 { // blake2f + // argsOffset[0; 3] (4 bytes) Number of rounds (big-endian uint) + gasToCharge := and(mload(argsOffset), 0xFFFFFFFF) // last 4bytes + } + default { + gasToCharge := 0 + } + } + + function checkMemOverflow(location, evmGasLeft) { + if gt(location, MAX_MEMORY_FRAME()) { + mstore(0, evmGasLeft) + revert(0, 32) + } + } + + function checkMultipleOverflow(data1, data2, data3, evmGasLeft) { + checkOverflow(data1, data2, evmGasLeft) + checkOverflow(data1, data3, evmGasLeft) + checkOverflow(data2, data3, evmGasLeft) + checkOverflow(add(data1, data2), data3, evmGasLeft) + } + + function checkOverflow(data1, data2, evmGasLeft) { + if lt(add(data1, data2), data2) { + revertWithGas(evmGasLeft) + } + } + + function revertWithGas(evmGasLeft) { + mstore(0, evmGasLeft) + revert(0, 32) + } + + // This function can overflow, it is the job of the caller to ensure that it does not. + // The argument to this function is the offset into the memory region IN BYTES. + function expandMemory(newSize) -> gasCost { + let oldSizeInWords := mload(MEM_OFFSET()) + + // The add 31 here before dividing is there to account for misaligned + // memory expansions, where someone calls this with a newSize that is not + // a multiple of 32. For instance, if someone calls it with an offset of 33, + // the new size in words should be 2, not 1, but dividing by 32 will give 1. + // Adding 31 solves it. + let newSizeInWords := div(add(newSize, 31), 32) + + if gt(newSizeInWords, oldSizeInWords) { + let new_minus_old := sub(newSizeInWords, oldSizeInWords) + gasCost := add(mul(3,new_minus_old), div(mul(new_minus_old,add(newSizeInWords,oldSizeInWords)),512)) + + mstore(MEM_OFFSET(), newSizeInWords) + } + } + + // Essentially a NOP that will not get optimized away by the compiler + function $llvm_NoInline_llvm$_unoptimized() { + pop(1) + } + + function printHex(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebde) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() + } + + function printString(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdf) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() + } + + function isSlotWarm(key) -> isWarm { + // TODO: Unhardcode this selector 0x482d2e74 + mstore8(0, 0x48) + mstore8(1, 0x2d) + mstore8(2, 0x2e) + mstore8(3, 0x74) + mstore(4, key) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + isWarm := mload(0) + } + + function warmSlot(key,currentValue) -> isWarm, originalValue { + // TODO: Unhardcode this selector 0xbdf78160 + mstore8(0, 0xbd) + mstore8(1, 0xf7) + mstore8(2, 0x81) + mstore8(3, 0x60) + mstore(4, key) + mstore(36,currentValue) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 64) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + isWarm := mload(0) + originalValue := mload(32) + } + + function MAX_SYSTEM_CONTRACT_ADDR() -> ret { + ret := 0x000000000000000000000000000000000000ffff + } + + /// @dev Checks whether an address is an EOA (i.e. has not code deployed on it) + /// @param addr The address to check + function isEOA(addr) -> ret { + ret := 0 + if gt(addr, MAX_SYSTEM_CONTRACT_ADDR()) { + ret := iszero(_getRawCodeHash(addr)) + } + } + + function getNewAddress(addr) -> newAddr { + let digest, nonce, addressEncoded, nonceEncoded, nonceEncodedLength, listLength, listLengthEconded + + nonce := getNonce(addr) + + addressEncoded := and( + add(addr, shl(160, 0x94)), + 0xffffffffffffffffffffffffffffffffffffffffff + ) + + nonceEncoded := nonce + nonceEncodedLength := 1 + if iszero(nonce) { + nonceEncoded := 128 + } + // The nonce has 4 bytes + if gt(nonce, 0xFFFFFF) { + nonceEncoded := shl(32, 0x84) + nonceEncoded := add(nonceEncoded, nonce) + nonceEncodedLength := 5 + } + // The nonce has 3 bytes + if and(gt(nonce, 0xFFFF), lt(nonce, 0x1000000)) { + nonceEncoded := shl(24, 0x83) + nonceEncoded := add(nonceEncoded, nonce) + nonceEncodedLength := 4 + } + // The nonce has 2 bytes + if and(gt(nonce, 0xFF), lt(nonce, 0x10000)) { + nonceEncoded := shl(16, 0x82) + nonceEncoded := add(nonceEncoded, nonce) + nonceEncodedLength := 3 + } + // The nonce has 1 byte and it's in [0x80, 0xFF] + if and(gt(nonce, 0x7F), lt(nonce, 0x100)) { + nonceEncoded := shl(8, 0x81) + nonceEncoded := add(nonceEncoded, nonce) + nonceEncodedLength := 2 + } + + listLength := add(21, nonceEncodedLength) + listLengthEconded := add(listLength, 0xC0) + + let arrayLength := add(168, mul(8, nonceEncodedLength)) + + digest := add( + shl(arrayLength, listLengthEconded), + add( + shl( + mul(8, nonceEncodedLength), + addressEncoded + ), + nonceEncoded + ) + ) + + mstore(0, shl(sub(248, arrayLength), digest)) + + newAddr := and( + keccak256(0, add(div(arrayLength, 8), 1)), + 0xffffffffffffffffffffffffffffffffffffffff + ) + } + + function incrementNonce(addr) { + mstore8(0, 0x30) + mstore8(1, 0x63) + mstore8(2, 0x95) + mstore8(3, 0xc6) + mstore(4, addr) + + let result := call(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 0, 36, 0, 0) + + if iszero(result) { + revert(0, 0) + } + } + + function ensureAcceptableMemLocation(location) { + if gt(location,MAX_POSSIBLE_MEM()) { + revert(0,0) // Check if this is whats needed + } + } + + function addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) -> newOffset,newSize { + newOffset := offset + newSize := size + if eq(isCallerEVM,1) { + // include gas + let previousValue := mload(sub(offset,32)) + mstore(sub(offset,32),evmGasLeft) + //mstore(sub(offset,32),previousValue) // Im not sure why this is needed, it was like this in the solidity code, + // but it appears to rewrite were we want to store the gas + + newOffset := sub(offset, 32) + newSize := add(size, 32) + } + } + + function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { + // TODO: Unhardcode this selector 0x8db2ba78 + mstore8(0, 0x8d) + mstore8(1, 0xb2) + mstore8(2, 0xba) + mstore8(3, 0x78) + mstore(4, addr) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + isWarm := mload(0) + } + + function getNonce(addr) -> nonce { + mstore8(0, 0xfb) + mstore8(1, 0x1a) + mstore8(2, 0x9a) + mstore8(3, 0x57) + mstore(4, addr) + + let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(result) { + revert(0, 0) + } + + nonce := mload(0) + } + + function getRawNonce(addr) -> nonce { + mstore8(0, 0x5a) + mstore8(1, 0xa9) + mstore8(2, 0xb6) + mstore8(3, 0xb5) + mstore(4, addr) + + let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(result) { + revert(0, 0) + } + + nonce := mload(0) + } + + function _isEVM(_addr) -> isEVM { + // bytes4 selector = ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM.selector; (0x8c040477) + // function isAccountEVM(address _addr) external view returns (bool); + // IAccountCodeStorage constant ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT = IAccountCodeStorage( + // address(SYSTEM_CONTRACTS_OFFSET + 0x02) + // ); + + mstore8(0, 0x8c) + mstore8(1, 0x04) + mstore8(2, 0x04) + mstore8(3, 0x77) + mstore(4, _addr) + + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + isEVM := mload(0) + } + + function _pushEVMFrame(_passGas, _isStatic) { + // function pushEVMFrame(uint256 _passGas, bool _isStatic) external + let selector := 0xead77156 + + mstore8(0, 0xea) + mstore8(1, 0xd7) + mstore8(2, 0x71) + mstore8(3, 0x56) + mstore(4, _passGas) + mstore(36, _isStatic) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 0) + if iszero(success) { + // This error should never happen + revert(0, 0) + } + } + + function _popEVMFrame() { + // function popEVMFrame() external + // 0xe467d2f0 + let selector := 0xe467d2f0 + + mstore8(0, 0xe4) + mstore8(1, 0x67) + mstore8(2, 0xd2) + mstore8(3, 0xf0) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 4, 0, 0) + if iszero(success) { + // This error should never happen + revert(0, 0) + } + } + + // Each evm gas is 5 zkEVM one + // FIXME: change this variable to reflect real ergs : gas ratio + function GAS_DIVISOR() -> gas_div { gas_div := 5 } + function EVM_GAS_STIPEND() -> gas_stipend { gas_stipend := shl(30, 1) } // 1 << 30 + function OVERHEAD() -> overhead { overhead := 2000 } + + // From precompiles/CodeOracle + function DECOMMIT_COST_PER_WORD() -> cost { cost := 4 } + function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 + + function _calcEVMGas(_zkevmGas) -> calczkevmGas { + calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) + } + + function getEVMGas() -> evmGas { + let _gas := gas() + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) + + switch lt(_gas, requiredGas) + case 1 { + evmGas := 0 + } + default { + evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) + } + } + + function _getZkEVMGas(_evmGas, addr) -> zkevmGas { + zkevmGas := mul(_evmGas, GAS_DIVISOR()) + let byteSize := extcodesize(addr) + let should_ceil := mod(byteSize, 32) + if gt(should_ceil, 0) { + byteSize := add(byteSize, sub(32, should_ceil)) + } + let decommitGasCost := mul(div(byteSize,32), DECOMMIT_COST_PER_WORD()) + zkevmGas := sub(zkevmGas, decommitGasCost) + if gt(zkevmGas, UINT32_MAX()) { + zkevmGas := UINT32_MAX() + } + } + + function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft{ + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + let rtsz := returndatasize() + + loadReturndataIntoActivePtr() + + // if (rtsz > 31) + switch gt(rtsz, 31) + case 0 { + // Unexpected return data. + _gasLeft := 0 + _eraseReturndataPointer() + } + default { + returndatacopy(0, 0, 32) + _gasLeft := mload(0) + + // We copy as much returndata as possible without going over the + // returndata size. + switch lt(sub(rtsz, 32), _outputLen) + case 0 { returndatacopy(_outputOffset, 32, _outputLen) } + default { returndatacopy(_outputOffset, 32, sub(rtsz, 32)) } + + mstore(lastRtSzOffset, sub(rtsz, 32)) + + // Skip the returnData + ptrAddIntoActive(32) + } + } + + function _eraseReturndataPointer() { + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + + let activePtrSize := getActivePtrDataSize() + ptrShrinkIntoActive(and(activePtrSize, 0xFFFFFFFF))// uint32(activePtrSize) + mstore(lastRtSzOffset, 0) + } + + function _saveReturndataAfterZkEVMCall() { + loadReturndataIntoActivePtr() + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + + mstore(lastRtSzOffset, returndatasize()) + } + + function performStaticCall(oldSp,evmGasLeft) -> extraCost, sp { + let gasToPass,addr, argsOffset, argsSize, retOffset, retSize + + popStackCheck(oldSp, evmGasLeft, 6) + gasToPass, sp := popStackItemWithoutCheck(oldSp) + addr, sp := popStackItemWithoutCheck(sp) + argsOffset, sp := popStackItemWithoutCheck(sp) + argsSize, sp := popStackItemWithoutCheck(sp) + retOffset, sp := popStackItemWithoutCheck(sp) + retSize, sp := popStackItemWithoutCheck(sp) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + checkMultipleOverflow(argsOffset,argsSize,MEM_OFFSET_INNER(), evmGasLeft) + checkMultipleOverflow(retOffset, retSize,MEM_OFFSET_INNER(), evmGasLeft) + + checkMemOverflow(add(add(argsOffset, argsSize), MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflow(add(add(retOffset, retSize), MEM_OFFSET_INNER()), evmGasLeft) + + extraCost := 0 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + extraCost := 2500 + } + + { + let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) + extraCost := add(extraCost,maxExpand) + } + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + if gt(gasToPass, maxGasToPass) { + gasToPass := maxGasToPass + } + + let frameGasLeft + let success + if _isEVM(addr) { + _pushEVMFrame(gasToPass, true) + // TODO Check the following comment from zkSync .sol. + // We can not just pass all gas here to prevert overflow of zkEVM gas counter + success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, 0, 0) + + frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + _popEVMFrame() + } + + // zkEVM native + if iszero(_isEVM(addr)) { + gasToPass := _getZkEVMGas(gasToPass, addr) + let zkevmGasBefore := gas() + success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, add(MEM_OFFSET_INNER(), retOffset), retSize) + _saveReturndataAfterZkEVMCall() + + let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + + frameGasLeft := 0 + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) + } + } + + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) + sp := pushStackItem(sp, success, evmGasLeft) + } + function capGas(evmGasLeft,oldGasToPass) -> gasToPass { + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + gasToPass := oldGasToPass + if gt(oldGasToPass, maxGasToPass) { + gasToPass := maxGasToPass + } + } + + function getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) -> maxExpand{ + maxExpand := add(retOffset, retSize) + switch lt(maxExpand,add(argsOffset, argsSize)) + case 0 { + maxExpand := expandMemory(maxExpand) + } + default { + maxExpand := expandMemory(add(argsOffset, argsSize)) + } + } + + function _performCall(addr,gasToPass,value,argsOffset,argsSize,retOffset,retSize,isStatic) -> success, frameGasLeft, gasToPassNew{ + gasToPassNew := gasToPass + let is_evm := _isEVM(addr) + if isStatic { + if value { + revertWithGas(gasToPassNew) + } + success, frameGasLeft:= _performStaticCall( + is_evm, + gasToPassNew, + addr, + argsOffset, + argsSize, + retOffset, + retSize + ) + } + + if and(is_evm, iszero(isStatic)) { + _pushEVMFrame(gasToPassNew, isStatic) + success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + _popEVMFrame() + } + + // zkEVM native + if and(iszero(is_evm), iszero(isStatic)) { + gasToPassNew := _getZkEVMGas(gasToPassNew, addr) + let zkevmGasBefore := gas() + success := call(gasToPassNew, addr, value, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + + frameGasLeft := 0 + if gt(gasToPassNew, gasUsed) { + frameGasLeft := sub(gasToPassNew, gasUsed) + } + } + } + + function performCall(oldSp, evmGasLeft, isStatic) -> extraCost, sp { + let gasToPass,addr,value,argsOffset,argsSize,retOffset,retSize + + popStackCheck(oldSp, evmGasLeft, 7) + gasToPass, sp := popStackItemWithoutCheck(oldSp) + addr, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + argsOffset, sp := popStackItemWithoutCheck(sp) + argsSize, sp := popStackItemWithoutCheck(sp) + retOffset, sp := popStackItemWithoutCheck(sp) + retSize, sp := popStackItemWithoutCheck(sp) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + // static_gas = 0 + // dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + positive_value_cost + value_to_empty_account_cost + // code_execution_cost is the cost of the called code execution (limited by the gas parameter). + // If address is warm, then address_access_cost is 100, otherwise it is 2600. See section access sets. + // If value is not 0, then positive_value_cost is 9000. In this case there is also a call stipend that is given to make sure that a basic fallback function can be called. 2300 is thus removed from the cost, and also added to the gas input. + // If value is not 0 and the address given points to an empty account, then value_to_empty_account_cost is 25000. An account is empty if its balance is 0, its nonce is 0 and it has no code. + + extraCost := 0 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + extraCost := 2500 + } + + if gt(value, 0) { + extraCost := add(extraCost,6700) + gasToPass := add(gasToPass,2300) + } + + if and(isAddrEmpty(addr), gt(value, 0)) { + extraCost := add(extraCost,25000) + } + { + let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) + extraCost := add(extraCost,maxExpand) + } + gasToPass := capGas(evmGasLeft,gasToPass) + + argsOffset := add(argsOffset,MEM_OFFSET_INNER()) + retOffset := add(retOffset,MEM_OFFSET_INNER()) + + checkOverflow(argsOffset,argsSize, evmGasLeft) + checkOverflow(retOffset,retSize, evmGasLeft) + + checkMemOverflow(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflow(add(retOffset, retSize), evmGasLeft) + + let success, frameGasLeft + success, frameGasLeft, gasToPass:= _performCall( + addr, + gasToPass, + value, + argsOffset, + argsSize, + retOffset, + retSize, + isStatic + ) + + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) + sp := pushStackItem(sp,success, evmGasLeft) + } + + function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost { + let addr, gasToPass, argsOffset, argsSize, retOffset, retSize + + sp := oldSp + isStatic := oldIsStatic + + popStackCheck(sp, evmGasLeft, 6) + gasToPass, sp := popStackItemWithoutCheck(sp) + addr, sp := popStackItemWithoutCheck(sp) + argsOffset, sp := popStackItemWithoutCheck(sp) + argsSize, sp := popStackItemWithoutCheck(sp) + retOffset, sp := popStackItemWithoutCheck(sp) + retSize, sp := popStackItemWithoutCheck(sp) + + // addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + checkMultipleOverflow(argsOffset,argsSize,MEM_OFFSET_INNER(), evmGasLeft) + checkMultipleOverflow(retOffset, retSize,MEM_OFFSET_INNER(), evmGasLeft) + + checkMemOverflow(add(add(argsOffset, argsSize), MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflow(add(add(retOffset, retSize), MEM_OFFSET_INNER()), evmGasLeft) + + if iszero(_isEVM(addr)) { + revertWithGas(evmGasLeft) + } + + extraCost := 0 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + extraCost := 2500 + } + + { + let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) + extraCost := add(extraCost,maxExpand) + } + gasToPass := capGas(evmGasLeft,gasToPass) + + // TODO: Do this + // if warmAccount(addr) { + // extraCost = GAS_WARM_ACCESS; + // } else { + // extraCost = GAS_COLD_ACCOUNT_ACCESS; + // } + + _pushEVMFrame(gasToPass, isStatic) + let success := delegatecall( + // We can not just pass all gas here to prevert overflow of zkEVM gas counter + EVM_GAS_STIPEND(), + addr, + add(MEM_OFFSET_INNER(), argsOffset), + argsSize, + 0, + 0 + ) + + let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + + _popEVMFrame() + + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) + sp := pushStackItem(sp, success, evmGasLeft) + } + + function getMessageCallGas ( + _value, + _gas, + _gasLeft, + _memoryCost, + _extraGas + ) -> gasPlusExtra, gasPlusStipend { + let callStipend := 2300 + if iszero(_value) { + callStipend := 0 + } + + switch lt(_gasLeft, add(_extraGas, _memoryCost)) + case 0 + { + let _gasTemp := sub(sub(_gasLeft, _extraGas), _memoryCost) + // From the Tangerine Whistle fork, gas is capped at all but one 64th (remaining_gas / 64) + // of the remaining gas of the current context. If a call tries to send more, the gas is + // changed to match the maximum allowed. + let maxGasToPass := sub(_gasTemp, shr(6, _gasTemp)) // _gas >> 6 == _gas/64 + if gt(_gas, maxGasToPass) { + _gas := maxGasToPass + } + gasPlusExtra := add(_gas, _extraGas) + gasPlusStipend := add(_gas, callStipend) + } + default { + gasPlusExtra := add(_gas, _extraGas) + gasPlusStipend := add(_gas, callStipend) + } + } + + function _performStaticCall( + _calleeIsEVM, + _calleeGas, + _callee, + _inputOffset, + _inputLen, + _outputOffset, + _outputLen + ) -> success, _gasLeft { + if _calleeIsEVM { + _pushEVMFrame(_calleeGas, true) + // TODO Check the following comment from zkSync .sol. + // We can not just pass all gas here to prevert overflow of zkEVM gas counter + success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) + + _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) + _popEVMFrame() + } + + // zkEVM native + if iszero(_calleeIsEVM) { + _calleeGas := _getZkEVMGas(_calleeGas, _callee) + let zkevmGasBefore := gas() + success := staticcall(_calleeGas, _callee, _inputOffset, _inputLen, _outputOffset, _outputLen) + + _saveReturndataAfterZkEVMCall() + + let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + + _gasLeft := 0 + if gt(_calleeGas, gasUsed) { + _gasLeft := sub(_calleeGas, gasUsed) + } + } + } + + function isAddrEmpty(addr) -> isEmpty { + isEmpty := 0 + if iszero(extcodesize(addr)) { // YUL doesn't have short-circuit evaluation + if iszero(balance(addr)) { + if iszero(getRawNonce(addr)) { + isEmpty := 1 + } + } + } + } + + function _fetchConstructorReturnGas() -> gasLeft { + //selector is 0x24e5ab4a + + mstore8(0, 0x24) + mstore8(1, 0xe5) + mstore8(2, 0xab) + mstore8(3, 0x4a) + + let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + gasLeft := mload(0) + } + + function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeftOld) -> result, evmGasLeft { + pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) + + _eraseReturndataPointer() + + let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) + + if lt(selfbalance(),value) { + revertWithGas(evmGasLeftOld) + } + + offset := add(MEM_OFFSET_INNER(), offset) + + sp := pushStackItem(sp, mload(sub(offset, 0x80)), evmGasLeftOld) + sp := pushStackItem(sp, mload(sub(offset, 0x60)), evmGasLeftOld) + sp := pushStackItem(sp, mload(sub(offset, 0x40)), evmGasLeftOld) + sp := pushStackItem(sp, mload(sub(offset, 0x20)), evmGasLeftOld) + + // Selector + mstore(sub(offset, 0x80), 0x5b16a23c) + // Arg1: address + mstore(sub(offset, 0x60), addr) + // Arg2: init code + // Where the arg starts (third word) + mstore(sub(offset, 0x40), 0x40) + // Length of the init code + mstore(sub(offset, 0x20), size) + + _pushEVMFrame(gasForTheCall, false) + + result := call(INF_PASS_GAS(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 0) + + let gasLeft + switch result + case 0 { + gasLeft := _saveReturndataAfterEVMCall(0, 0) + } + default { + gasLeft := _fetchConstructorReturnGas() + } + + let gasUsed := sub(gasForTheCall, gasLeft) + evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) + + _popEVMFrame() + + switch result + case 1 { + incrementNonce(address()) + } + default { + switch isEOA(address()) + case 1 { + incrementNonce(address()) + } + default {} + } + + let back + + popStackCheck(sp, evmGasLeft, 4) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x20), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x40), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x60), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x80), back) + } + + function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { + evmGasLeft := chargeGas(evmGas, 100) + + let addr, dest, offset, len + popStackCheck(oldSp, evmGasLeft, 4) + addr, sp := popStackItemWithoutCheck(oldSp) + dest, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + len, sp := popStackItemWithoutCheck(sp) + + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost + // minimum_word_size = (size + 31) / 32 + + let dynamicGas := add( + mul(3, shr(5, add(len, 31))), + expandMemory(add(dest, len)) + ) + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + dynamicGas := add(dynamicGas, 2500) + } + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + let len_32 := shr(5, len) + for {let i := 0} lt(i, len_32) { i := add(i, 1) } { + mstore(add(dest,shl(5,i)),0) + } + let size_32 := shl(5,len_32) + let rest_32 := sub(len, size_32) + for {let i := 0} lt(i, rest_32) { i := add(i, 1) } { + mstore8(add(dest,add(size_32,i)),0) + } + + // Gets the code from the addr + if iszero(iszero(_getRawCodeHash(addr))) { + pop(_fetchDeployedCodeWithDest(addr, offset, len,add(dest,MEM_OFFSET_INNER()))) + } + + } + + function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { + evmGasLeft := chargeGas(evmGas, 32000) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let value, offset, size + + popStackCheck(oldSp, evmGasLeft, 3) + value, sp := popStackItemWithoutCheck(oldSp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) + + checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + + if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { + revertWithGas(evmGasLeft) + } + + if gt(value, balance(address())) { + revertWithGas(evmGasLeft) + } + + // dynamicGas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost + // minimum_word_size = (size + 31) / 32 + // init_code_cost = 2 * minimum_word_size + // code_deposit_cost = 200 * deployed_code_size + let dynamicGas := add( + shr(4, add(size, 31)), + expandMemory(add(offset, size)) + ) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + let addr := getNewAddress(address()) + + let result + result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + + switch result + case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } + default { sp := pushStackItem(sp, addr, evmGasLeft) } + } + + function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr{ + evmGasLeft := chargeGas(evmGas, 32000) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let value, offset, size, salt + + popStackCheck(oldSp, evmGasLeft, 4) + value, sp := popStackItemWithoutCheck(oldSp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + salt, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) + + checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + + if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { + revertWithGas(evmGasLeft) + } + + if gt(value, balance(address())) { + revertWithGas(evmGasLeft) + } + + // dynamicGas = init_code_cost + hash_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost + // minimum_word_size = (size + 31) / 32 + // init_code_cost = 2 * minimum_word_size + // hash_cost = 6 * minimum_word_size + // code_deposit_cost = 200 * deployed_code_size + evmGasLeft := chargeGas(evmGasLeft, add( + expandMemory(add(offset, size)), + shr(2, add(size, 31)) + )) + + { + let hashedBytecode := keccak256(add(MEM_OFFSET_INNER(), offset), size) + mstore8(0, 0xFF) + mstore(0x01, shl(0x60, address())) + mstore(0x15, salt) + mstore(0x35, hashedBytecode) + } + + addr := and( + keccak256(0, 0x55), + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + ) + + result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + } + + + function $llvm_NoInline_llvm$_simulate( + isCallerEVM, + evmGasLeft, + isStatic, + ) -> returnOffset, returnLen { + + returnOffset := MEM_OFFSET_INNER() + returnLen := 0 + + // stack pointer - index to first stack element; empty stack = -1 + let sp := sub(STACK_OFFSET(), 32) + // instruction pointer - index to next instruction. Not called pc because it's an + // actual yul/evm instruction. + let ip := add(BYTECODE_OFFSET(), 32) + let opcode + + let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) + + for { } true { } { + opcode := readIP(ip,maxAcceptablePos) + + switch opcode + case 0x00 { // OP_STOP + break + } + case 0x01 { // OP_ADD + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, add(a, b)) + ip := add(ip, 1) + } + case 0x02 { // OP_MUL + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, mul(a, b)) + ip := add(ip, 1) + } + case 0x03 { // OP_SUB + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sub(a, b)) + ip := add(ip, 1) + } + case 0x04 { // OP_DIV + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, div(a, b)) + ip := add(ip, 1) + } + case 0x05 { // OP_SDIV + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sdiv(a, b)) + ip := add(ip, 1) + } + case 0x06 { // OP_MOD + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, mod(a, b)) + ip := add(ip, 1) + } + case 0x07 { // OP_SMOD + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, smod(a, b)) + ip := add(ip, 1) + } + case 0x08 { // OP_ADDMOD + evmGasLeft := chargeGas(evmGasLeft, 8) + + let a, b, N + + popPushStackCheck(sp, evmGasLeft, 3) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + N, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, addmod(a, b, N)) + ip := add(ip, 1) + } + case 0x09 { // OP_MULMOD + evmGasLeft := chargeGas(evmGasLeft, 8) + + let a, b, N + + popStackCheck(sp, evmGasLeft, 3) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + N, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItem(sp, mulmod(a, b, N), evmGasLeft) + ip := add(ip, 1) + } + case 0x0A { // OP_EXP + evmGasLeft := chargeGas(evmGasLeft, 10) + + let a, exponent + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + exponent, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, exp(a, exponent)) + + let to_charge := 0 + for {} gt(exponent,0) {} { // while exponent > 0 + to_charge := add(to_charge, 50) + exponent := shr(8, exponent) + } + evmGasLeft := chargeGas(evmGasLeft, to_charge) + ip := add(ip, 1) + } + case 0x0B { // OP_SIGNEXTEND + evmGasLeft := chargeGas(evmGasLeft, 5) + + let b, x + + popPushStackCheck(sp, evmGasLeft, 2) + b, sp := popStackItemWithoutCheck(sp) + x, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, signextend(b, x)) + ip := add(ip, 1) + } + case 0x10 { // OP_LT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, lt(a, b)) + ip := add(ip, 1) + } + case 0x11 { // OP_GT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, gt(a, b)) + ip := add(ip, 1) + } + case 0x12 { // OP_SLT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, slt(a, b)) + ip := add(ip, 1) + } + case 0x13 { // OP_SGT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sgt(a, b)) + ip := add(ip, 1) + } + case 0x14 { // OP_EQ + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, eq(a, b)) + ip := add(ip, 1) + } + case 0x15 { // OP_ISZERO + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a + + popPushStackCheck(sp, evmGasLeft, 1) + a, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, iszero(a)) + ip := add(ip, 1) + } + case 0x16 { // OP_AND + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, and(a,b)) + ip := add(ip, 1) + } + case 0x17 { // OP_OR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, or(a,b)) + ip := add(ip, 1) + } + case 0x18 { // OP_XOR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popPushStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, xor(a, b)) + ip := add(ip, 1) + } + case 0x19 { // OP_NOT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a + + popPushStackCheck(sp, evmGasLeft, 1) + a, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, not(a)) + ip := add(ip, 1) + } + case 0x1A { // OP_BYTE + evmGasLeft := chargeGas(evmGasLeft, 3) + + let i, x + + popPushStackCheck(sp, evmGasLeft, 2) + i, sp := popStackItemWithoutCheck(sp) + x, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, byte(i, x)) + ip := add(ip, 1) + } + case 0x1B { // OP_SHL + evmGasLeft := chargeGas(evmGasLeft, 3) + + let shift, value + + popPushStackCheck(sp, evmGasLeft, 2) + shift, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, shl(shift, value)) + ip := add(ip, 1) + } + case 0x1C { // OP_SHR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let shift, value + + popPushStackCheck(sp, evmGasLeft, 2) + shift, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, shr(shift, value)) + ip := add(ip, 1) + } + case 0x1D { // OP_SAR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let shift, value + + popPushStackCheck(sp, evmGasLeft, 2) + shift, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sar(shift, value)) + ip := add(ip, 1) + } + case 0x20 { // OP_KECCAK256 + evmGasLeft := chargeGas(evmGasLeft, 30) + + let offset, size + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) + checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + let keccak := keccak256(add(MEM_OFFSET_INNER(), offset), size) + + // When an offset is first accessed (either read or write), memory may trigger + // an expansion, which costs gas. + // dynamicGas = 6 * minimum_word_size + memory_expansion_cost + // minimum_word_size = (size + 31) / 32 + let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + sp := pushStackItem(sp, keccak, evmGasLeft) + ip := add(ip, 1) + } + case 0x30 { // OP_ADDRESS + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, address(), evmGasLeft) + ip := add(ip, 1) + } + case 0x31 { // OP_BALANCE + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr + + addr, sp := popStackItem(sp, evmGasLeft) + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + evmGasLeft := chargeGas(evmGasLeft, 2500) + } + + sp := pushStackItem(sp, balance(addr), evmGasLeft) + ip := add(ip, 1) + } + case 0x32 { // OP_ORIGIN + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, origin(), evmGasLeft) + ip := add(ip, 1) + } + case 0x33 { // OP_CALLER + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, caller(), evmGasLeft) + ip := add(ip, 1) + } + case 0x34 { // OP_CALLVALUE + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, callvalue(), evmGasLeft) + ip := add(ip, 1) + } + case 0x35 { // OP_CALLDATALOAD + evmGasLeft := chargeGas(evmGasLeft, 3) + + let i + + popPushStackCheck(sp, evmGasLeft, 1) + i, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, calldataload(i)) + ip := add(ip, 1) + } + case 0x36 { // OP_CALLDATASIZE + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, calldatasize(), evmGasLeft) + ip := add(ip, 1) + } + case 0x37 { // OP_CALLDATACOPY + evmGasLeft := chargeGas(evmGasLeft, 3) + + let destOffset, offset, size + + popStackCheck(sp, evmGasLeft, 3) + destOffset, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset,size,MEM_OFFSET_INNER(), evmGasLeft) + checkMultipleOverflow(destOffset,size,MEM_OFFSET_INNER(), evmGasLeft) + + if or(gt(add(add(offset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM()), gt(add(add(destOffset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM())) { + for { let i := 0 } lt(i, size) { i := add(i, 1) } { + mstore8( + add(add(destOffset, MEM_OFFSET_INNER()), i), + 0 + ) + } + } + + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + // minimum_word_size = (size + 31) / 32 + let dynamicGas := add(mul(3, shr(5, add(size, 31))), expandMemory(add(destOffset, size))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + calldatacopy(add(destOffset, MEM_OFFSET_INNER()), offset, size) + ip := add(ip, 1) + + } + case 0x38 { // OP_CODESIZE + evmGasLeft := chargeGas(evmGasLeft, 2) + + let bytecodeLen := mload(BYTECODE_OFFSET()) + sp := pushStackItem(sp, bytecodeLen, evmGasLeft) + ip := add(ip, 1) + } + case 0x39 { // OP_CODECOPY + + evmGasLeft := chargeGas(evmGasLeft, 3) + + let dst, offset, len + + popStackCheck(sp, evmGasLeft, 3) + dst, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + len, sp := popStackItemWithoutCheck(sp) + + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + // minimum_word_size = (size + 31) / 32 + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dst, len))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + dst := add(dst, MEM_OFFSET_INNER()) + offset := add(add(offset, BYTECODE_OFFSET()), 32) + + checkOverflow(dst,len, evmGasLeft) + checkMemOverflow(add(dst, len), evmGasLeft) + // Check bytecode overflow + if gt(add(offset, len), sub(MEM_OFFSET(), 1)) { + revertWithGas(evmGasLeft) + } + + for { let i := 0 } lt(i, len) { i := add(i, 1) } { + mstore8( + add(dst, i), + shr(248, mload(add(offset, i))) + ) + } + ip := add(ip, 1) + } + case 0x3A { // OP_GASPRICE + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, gasprice(), evmGasLeft) + ip := add(ip, 1) + } + case 0x3B { // OP_EXTCODESIZE + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr + addr, sp := popStackItem(sp, evmGasLeft) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + evmGasLeft := chargeGas(evmGasLeft, 2500) + } + + // TODO: check, the .sol uses extcodesize directly, but it doesnt seem to work + // if a contract is created it works, but if the address is a zkSync's contract + // what happens? + // sp := pushStackItem(sp, extcodesize(addr), evmGasLeft) + + switch _isEVM(addr) + case 0 { sp := pushStackItem(sp, extcodesize(addr), evmGasLeft) } + default { sp := pushStackItem(sp, _fetchDeployedCodeLen(addr), evmGasLeft) } + ip := add(ip, 1) + } + case 0x3C { // OP_EXTCODECOPY + evmGasLeft, sp := performExtCodeCopy(evmGasLeft, sp) + ip := add(ip, 1) + } + case 0x3D { // OP_RETURNDATASIZE + evmGasLeft := chargeGas(evmGasLeft, 2) + + let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) + sp := pushStackItem(sp, rdz, evmGasLeft) + ip := add(ip, 1) + } + case 0x3E { // OP_RETURNDATACOPY + evmGasLeft := chargeGas(evmGasLeft, 3) + + let dest, offset, len + popStackCheck(sp, evmGasLeft, 3) + dest, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + len, sp := popStackItemWithoutCheck(sp) + + // TODO: check if these conditions are met + // The addition offset + size overflows. + // offset + size is larger than RETURNDATASIZE. + checkOverflow(offset,len, evmGasLeft) + if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + // minimum_word_size = (size + 31) / 32 + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dest, len))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + copyActivePtrData(add(MEM_OFFSET_INNER(), dest), offset, len) + ip := add(ip, 1) + } + case 0x3F { // OP_EXTCODEHASH + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr + addr, sp := popStackItem(sp, evmGasLeft) + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + evmGasLeft := chargeGas(evmGasLeft, 2500) + } + + ip := add(ip, 1) + if iszero(addr) { + sp := pushStackItem(sp, 0, evmGasLeft) + continue + } + sp := pushStackItem(sp, extcodehash(addr), evmGasLeft) + } + case 0x40 { // OP_BLOCKHASH + evmGasLeft := chargeGas(evmGasLeft, 20) + + let blockNumber + popPushStackCheck(sp, evmGasLeft, 1) + blockNumber, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, blockhash(blockNumber)) + ip := add(ip, 1) + } + case 0x41 { // OP_COINBASE + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, coinbase(), evmGasLeft) + ip := add(ip, 1) + } + case 0x42 { // OP_TIMESTAMP + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, timestamp(), evmGasLeft) + ip := add(ip, 1) + } + case 0x43 { // OP_NUMBER + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, number(), evmGasLeft) + ip := add(ip, 1) + } + case 0x44 { // OP_PREVRANDAO + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, prevrandao(), evmGasLeft) + ip := add(ip, 1) + } + case 0x45 { // OP_GASLIMIT + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, gaslimit(), evmGasLeft) + ip := add(ip, 1) + } + case 0x46 { // OP_CHAINID + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, chainid(), evmGasLeft) + ip := add(ip, 1) + } + case 0x47 { // OP_SELFBALANCE + evmGasLeft := chargeGas(evmGasLeft, 5) + sp := pushStackItem(sp, selfbalance(), evmGasLeft) + ip := add(ip, 1) + } + case 0x48 { // OP_BASEFEE + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, basefee(), evmGasLeft) + ip := add(ip, 1) + } + case 0x50 { // OP_POP + evmGasLeft := chargeGas(evmGasLeft, 2) + + let _y + + _y, sp := popStackItem(sp, evmGasLeft) + ip := add(ip, 1) + } + case 0x51 { // OP_MLOAD + evmGasLeft := chargeGas(evmGasLeft, 3) + + let offset + + offset, sp := popStackItem(sp, evmGasLeft) + + checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + let expansionGas := expandMemory(add(offset, 32)) + evmGasLeft := chargeGas(evmGasLeft, expansionGas) + + checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + let memValue := mload(add(MEM_OFFSET_INNER(), offset)) + sp := pushStackItem(sp, memValue, evmGasLeft) + ip := add(ip, 1) + } + case 0x52 { // OP_MSTORE + evmGasLeft := chargeGas(evmGasLeft, 3) + + let offset, value + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + let expansionGas := expandMemory(add(offset, 32)) + evmGasLeft := chargeGas(evmGasLeft, expansionGas) + + checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + mstore(add(MEM_OFFSET_INNER(), offset), value) + ip := add(ip, 1) + } + case 0x53 { // OP_MSTORE8 + evmGasLeft := chargeGas(evmGasLeft, 3) + + let offset, value + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + let expansionGas := expandMemory(add(offset, 1)) + evmGasLeft := chargeGas(evmGasLeft, expansionGas) + + checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + mstore8(add(MEM_OFFSET_INNER(), offset), value) + ip := add(ip, 1) + } + case 0x54 { // OP_SLOAD + + evmGasLeft := chargeGas(evmGasLeft, 100) + + let key, value, isWarm + + key, sp := popStackItem(sp, evmGasLeft) + + let wasWarm := isSlotWarm(key) + + if iszero(wasWarm) { + evmGasLeft := chargeGas(evmGasLeft, 2000) + } + + value := sload(key) + + if iszero(wasWarm) { + let _wasW, _orgV := warmSlot(key, value) + } + + sp := pushStackItem(sp,value, evmGasLeft) + ip := add(ip, 1) + } + case 0x55 { // OP_SSTORE + evmGasLeft := chargeGas(evmGasLeft, 100) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let key, value, gasSpent + + popStackCheck(sp, evmGasLeft, 2) + key, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + ip := add(ip, 1) + { + // Here it is okay to read before we charge since we known anyway that + // the context has enough funds to compensate at least for the read. + // Im not sure if we need this before: require(gasLeft > GAS_CALL_STIPEND); + let currentValue := sload(key) + let wasWarm, originalValue := warmSlot(key, currentValue) + + if eq(value, currentValue) { + continue + } + + if eq(originalValue, currentValue) { + gasSpent := 19900 + if originalValue { + gasSpent := 2800 + } + } + + if iszero(wasWarm) { + gasSpent := add(gasSpent, 2100) + } + } + + evmGasLeft := chargeGas(evmGasLeft, gasSpent) + sstore(key, value) + + } + // NOTE: We don't currently do full jumpdest validation + // (i.e. validating a jumpdest isn't in PUSH data) + case 0x56 { // OP_JUMP + evmGasLeft := chargeGas(evmGasLeft, 8) + + let counter + + counter, sp := popStackItem(sp, evmGasLeft) + + ip := add(add(BYTECODE_OFFSET(), 32), counter) + + // Check next opcode is JUMPDEST + let nextOpcode := readIP(ip,maxAcceptablePos) + if iszero(eq(nextOpcode, 0x5B)) { + revertWithGas(evmGasLeft) + } + } + case 0x57 { // OP_JUMPI + evmGasLeft := chargeGas(evmGasLeft, 10) + + let counter, b + + popStackCheck(sp, evmGasLeft, 2) + counter, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + if iszero(b) { + ip := add(ip, 1) + continue + } + + ip := add(add(BYTECODE_OFFSET(), 32), counter) + + // Check next opcode is JUMPDEST + let nextOpcode := readIP(ip,maxAcceptablePos) + if iszero(eq(nextOpcode, 0x5B)) { + revertWithGas(evmGasLeft) + } + } + case 0x58 { // OP_PC + evmGasLeft := chargeGas(evmGasLeft, 2) + ip := add(ip, 1) + + // PC = ip - 32 (bytecode size) - 1 (current instruction) + sp := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft) + } + case 0x59 { // OP_MSIZE + evmGasLeft := chargeGas(evmGasLeft,2) + + let size + + size := mload(MEM_OFFSET()) + size := shl(5,size) + sp := pushStackItem(sp,size, evmGasLeft) + ip := add(ip, 1) + } + case 0x5A { // OP_GAS + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, evmGasLeft, evmGasLeft) + ip := add(ip, 1) + } + case 0x5B { // OP_JUMPDEST + evmGasLeft := chargeGas(evmGasLeft, 1) + ip := add(ip, 1) + } + case 0x5C { // OP_TLOAD + evmGasLeft := chargeGas(evmGasLeft, 100) + + let key + popPushStackCheck(sp, evmGasLeft, 1) + key, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, tload(key)) + ip := add(ip, 1) + } + case 0x5D { // OP_TSTORE + evmGasLeft := chargeGas(evmGasLeft, 100) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let key, value + popStackCheck(sp, evmGasLeft, 2) + key, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + tstore(key, value) + ip := add(ip, 1) + } + case 0x5E { // OP_MCOPY + let destOffset, offset, size + popStackCheck(sp, evmGasLeft, 3) + destOffset, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + expandMemory(add(destOffset, size)) + expandMemory(add(offset, size)) + + let oldSize := mul(mload(MEM_OFFSET()),32) + if gt(add(oldSize,size),MAX_POSSIBLE_MEM()) { + revertWithGas(evmGasLeft) + } + + for { let i := 0 } lt(i, size) { i := add(i, 1) } { + mstore8( + add(add(oldSize,MEM_OFFSET_INNER()), i), + shr(248,mload(add(add(offset,MEM_OFFSET_INNER()), i))) + ) + } + for { let i := 0 } lt(i, size) { i := add(i, 1) } { + mstore8( + add(add(destOffset,MEM_OFFSET_INNER()), i), + shr(248,mload(add(add(oldSize,MEM_OFFSET_INNER()), i))) + ) + } + ip := add(ip, 1) + } + case 0x5F { // OP_PUSH0 + evmGasLeft := chargeGas(evmGasLeft, 2) + + let value := 0 + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 1) + } + case 0x60 { // OP_PUSH1 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,1) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 1) + } + case 0x61 { // OP_PUSH2 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,2) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 2) + } + case 0x62 { // OP_PUSH3 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,3) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 3) + } + case 0x63 { // OP_PUSH4 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,4) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 4) + } + case 0x64 { // OP_PUSH5 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,5) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 5) + } + case 0x65 { // OP_PUSH6 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,6) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 6) + } + case 0x66 { // OP_PUSH7 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,7) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 7) + } + case 0x67 { // OP_PUSH8 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,8) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 8) + } + case 0x68 { // OP_PUSH9 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,9) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 9) + } + case 0x69 { // OP_PUSH10 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,10) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 10) + } + case 0x6A { // OP_PUSH11 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,11) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 11) + } + case 0x6B { // OP_PUSH12 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,12) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 12) + } + case 0x6C { // OP_PUSH13 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,13) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 13) + } + case 0x6D { // OP_PUSH14 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,14) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 14) + } + case 0x6E { // OP_PUSH15 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,15) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 15) + } + case 0x6F { // OP_PUSH16 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,16) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 16) + } + case 0x70 { // OP_PUSH17 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,17) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 17) + } + case 0x71 { // OP_PUSH18 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,18) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 18) + } + case 0x72 { // OP_PUSH19 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,19) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 19) + } + case 0x73 { // OP_PUSH20 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,20) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 20) + } + case 0x74 { // OP_PUSH21 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,21) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 21) + } + case 0x75 { // OP_PUSH22 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,22) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 22) + } + case 0x76 { // OP_PUSH23 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,23) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 23) + } + case 0x77 { // OP_PUSH24 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,24) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 24) + } + case 0x78 { // OP_PUSH25 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,25) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 25) + } + case 0x79 { // OP_PUSH26 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,26) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 26) + } + case 0x7A { // OP_PUSH27 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,27) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 27) + } + case 0x7B { // OP_PUSH28 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,28) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 28) + } + case 0x7C { // OP_PUSH29 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,29) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 29) + } + case 0x7D { // OP_PUSH30 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,30) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 30) + } + case 0x7E { // OP_PUSH31 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,31) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 31) + } + case 0x7F { // OP_PUSH32 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,32) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 32) + } + case 0x80 { // OP_DUP1 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 1) + ip := add(ip, 1) + } + case 0x81 { // OP_DUP2 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 2) + ip := add(ip, 1) + } + case 0x82 { // OP_DUP3 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 3) + ip := add(ip, 1) + } + case 0x83 { // OP_DUP4 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 4) + ip := add(ip, 1) + } + case 0x84 { // OP_DUP5 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 5) + ip := add(ip, 1) + } + case 0x85 { // OP_DUP6 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 6) + ip := add(ip, 1) + } + case 0x86 { // OP_DUP7 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 7) + ip := add(ip, 1) + } + case 0x87 { // OP_DUP8 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 8) + ip := add(ip, 1) + } + case 0x88 { // OP_DUP9 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 9) + ip := add(ip, 1) + } + case 0x89 { // OP_DUP10 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 10) + ip := add(ip, 1) + } + case 0x8A { // OP_DUP11 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 11) + ip := add(ip, 1) + } + case 0x8B { // OP_DUP12 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 12) + ip := add(ip, 1) + } + case 0x8C { // OP_DUP13 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 13) + ip := add(ip, 1) + } + case 0x8D { // OP_DUP14 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 14) + ip := add(ip, 1) + } + case 0x8E { // OP_DUP15 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 15) + ip := add(ip, 1) + } + case 0x8F { // OP_DUP16 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 16) + ip := add(ip, 1) + } + case 0x90 { // OP_SWAP1 + evmGasLeft := swapStackItem(sp, evmGasLeft, 1) + ip := add(ip, 1) + } + case 0x91 { // OP_SWAP2 + evmGasLeft := swapStackItem(sp, evmGasLeft, 2) + ip := add(ip, 1) + } + case 0x92 { // OP_SWAP3 + evmGasLeft := swapStackItem(sp, evmGasLeft, 3) + ip := add(ip, 1) + } + case 0x93 { // OP_SWAP4 + evmGasLeft := swapStackItem(sp, evmGasLeft, 4) + ip := add(ip, 1) + } + case 0x94 { // OP_SWAP5 + evmGasLeft := swapStackItem(sp, evmGasLeft, 5) + ip := add(ip, 1) + } + case 0x95 { // OP_SWAP6 + evmGasLeft := swapStackItem(sp, evmGasLeft, 6) + ip := add(ip, 1) + } + case 0x96 { // OP_SWAP7 + evmGasLeft := swapStackItem(sp, evmGasLeft, 7) + ip := add(ip, 1) + } + case 0x97 { // OP_SWAP8 + evmGasLeft := swapStackItem(sp, evmGasLeft, 8) + ip := add(ip, 1) + } + case 0x98 { // OP_SWAP9 + evmGasLeft := swapStackItem(sp, evmGasLeft, 9) + ip := add(ip, 1) + } + case 0x99 { // OP_SWAP10 + evmGasLeft := swapStackItem(sp, evmGasLeft, 10) + ip := add(ip, 1) + } + case 0x9A { // OP_SWAP11 + evmGasLeft := swapStackItem(sp, evmGasLeft, 11) + ip := add(ip, 1) + } + case 0x9B { // OP_SWAP12 + evmGasLeft := swapStackItem(sp, evmGasLeft, 12) + ip := add(ip, 1) + } + case 0x9C { // OP_SWAP13 + evmGasLeft := swapStackItem(sp, evmGasLeft, 13) + ip := add(ip, 1) + } + case 0x9D { // OP_SWAP14 + evmGasLeft := swapStackItem(sp, evmGasLeft, 14) + ip := add(ip, 1) + } + case 0x9E { // OP_SWAP15 + evmGasLeft := swapStackItem(sp, evmGasLeft, 15) + ip := add(ip, 1) + } + case 0x9F { // OP_SWAP16 + evmGasLeft := swapStackItem(sp, evmGasLeft, 16) + ip := add(ip, 1) + } + case 0xA0 { // OP_LOG0 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) + checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + log0(add(offset, MEM_OFFSET_INNER()), size) + ip := add(ip, 1) + } + case 0xA1 { // OP_LOG1 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size, topic1 + popStackCheck(sp, evmGasLeft, 3) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + topic1, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) + checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 375) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + ip := add(ip, 1) + } + case 0xA2 { // OP_LOG2 + evmGasLeft := chargeGas(evmGasLeft, 375) + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) + checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 750) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + { + let topic1, topic2 + popStackCheck(sp, evmGasLeft, 2) + topic1, sp := popStackItemWithoutCheck(sp) + topic2, sp := popStackItemWithoutCheck(sp) + log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) + } + ip := add(ip, 1) + } + case 0xA3 { // OP_LOG3 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) + + checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 1125) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + { + let topic1, topic2, topic3 + popStackCheck(sp, evmGasLeft, 3) + topic1, sp := popStackItemWithoutCheck(sp) + topic2, sp := popStackItemWithoutCheck(sp) + topic3, sp := popStackItemWithoutCheck(sp) + log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) + } + ip := add(ip, 1) + } + case 0xA4 { // OP_LOG4 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) + checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 1500) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + { + let topic1, topic2, topic3, topic4 + popStackCheck(sp, evmGasLeft, 4) + topic1, sp := popStackItemWithoutCheck(sp) + topic2, sp := popStackItemWithoutCheck(sp) + topic3, sp := popStackItemWithoutCheck(sp) + topic4, sp := popStackItemWithoutCheck(sp) + log4(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3, topic4) + } + ip := add(ip, 1) + } + case 0xF0 { // OP_CREATE + evmGasLeft, sp := performCreate(evmGasLeft, sp, isStatic) + ip := add(ip, 1) + } + case 0xF1 { // OP_CALL + evmGasLeft := chargeGas(evmGasLeft, 100) + + let gasUsed + + // A function was implemented in order to avoid stack depth errors. + gasUsed, sp := performCall(sp, evmGasLeft, isStatic) + + // Check if the following is ok + evmGasLeft := chargeGas(evmGasLeft, gasUsed) + ip := add(ip, 1) + } + case 0xF3 { // OP_RETURN + let offset,size + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset,size, evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + + returnLen := size + checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + returnOffset := add(MEM_OFFSET_INNER(), offset) + break + } + case 0xF4 { // OP_DELEGATECALL + evmGasLeft := chargeGas(evmGasLeft, 100) + + let gasUsed + sp, isStatic, gasUsed := delegateCall(sp, isStatic, evmGasLeft) + + evmGasLeft := chargeGas(evmGasLeft, gasUsed) + ip := add(ip, 1) + } + case 0xF5 { // OP_CREATE2 + let result, addr + evmGasLeft, sp, result, addr := performCreate2(evmGasLeft, sp, isStatic) + switch result + case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } + default { sp := pushStackItem(sp, addr, evmGasLeft) } + ip := add(ip, 1) + } + case 0xFA { // OP_STATICCALL + evmGasLeft := chargeGas(evmGasLeft, 100) + + let gasUsed + gasUsed, sp := performStaticCall(sp,evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft,gasUsed) + ip := add(ip, 1) + } + case 0xFD { // OP_REVERT + let offset,size + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + ensureAcceptableMemLocation(offset) + ensureAcceptableMemLocation(size) + evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + + offset := add(offset, MEM_OFFSET_INNER()) + offset,size := addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) + + revert(offset,size) + } + case 0xFE { // OP_INVALID + evmGasLeft := 0 + + revertWithGas(evmGasLeft) + } + default { + printString("INVALID OPCODE") + printHex(opcode) + revert(0, 0) + } + } + + + if eq(isCallerEVM, 1) { + // Includes gas + returnOffset := sub(returnOffset, 32) + checkOverflow(returnLen, 32, evmGasLeft) + returnLen := add(returnLen, 32) + + mstore(returnOffset, evmGasLeft) + } + } + + //////////////////////////////////////////////////////////////// + // FALLBACK + //////////////////////////////////////////////////////////////// + + let evmGasLeft, isStatic, isCallerEVM := consumeEvmFrame() + + if iszero(isCallerEVM) { + evmGasLeft := getEVMGas() + isStatic := getIsStaticFromCallFlags() + } + + // First, copy the contract's bytecode to be executed into tEdhe `BYTECODE_OFFSET` + // segment of memory. + getDeployedBytecode() + + pop($llvm_AlwaysInline_llvm$_warmAddress(address())) + + let returnOffset, returnLen := $llvm_NoInline_llvm$_simulate(isCallerEVM, evmGasLeft, isStatic) + return(returnOffset, returnLen) + } + } +} diff --git a/system-contracts/contracts/GasBoundCaller.sol b/system-contracts/contracts/GasBoundCaller.sol index d45f64163..d927e25d5 100644 --- a/system-contracts/contracts/GasBoundCaller.sol +++ b/system-contracts/contracts/GasBoundCaller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {EfficientCall} from "./libraries/EfficientCall.sol"; import {REAL_SYSTEM_CONTEXT_CONTRACT} from "./Constants.sol"; diff --git a/system-contracts/contracts/ImmutableSimulator.sol b/system-contracts/contracts/ImmutableSimulator.sol index 2d077316a..346a44416 100644 --- a/system-contracts/contracts/ImmutableSimulator.sol +++ b/system-contracts/contracts/ImmutableSimulator.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IImmutableSimulator, ImmutableData} from "./interfaces/IImmutableSimulator.sol"; import {DEPLOYER_SYSTEM_CONTRACT} from "./Constants.sol"; diff --git a/system-contracts/contracts/KnownCodesStorage.sol b/system-contracts/contracts/KnownCodesStorage.sol index 3db07fe31..b8761e14f 100644 --- a/system-contracts/contracts/KnownCodesStorage.sol +++ b/system-contracts/contracts/KnownCodesStorage.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IKnownCodesStorage} from "./interfaces/IKnownCodesStorage.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; import {Utils} from "./libraries/Utils.sol"; -import {COMPRESSOR_CONTRACT, L1_MESSENGER_CONTRACT} from "./Constants.sol"; +import {COMPRESSOR_CONTRACT, L1_MESSENGER_CONTRACT, DEPLOYER_SYSTEM_CONTRACT} from "./Constants.sol"; /** * @author Matter Labs @@ -77,4 +77,22 @@ contract KnownCodesStorage is IKnownCodesStorage, ISystemContract { require(Utils.bytecodeLenInWords(_bytecodeHash) % 2 == 1, "Code length in words must be odd"); } + + function publishEVMBytecode(bytes calldata bytecode) external onlyCallFrom(address(DEPLOYER_SYSTEM_CONTRACT)) { + /* + TODO: ensure that it is properly padded, etc. + To preserve EVM compatibility, we can not emit any events here. + */ + + bytes32 hash = Utils.hashEVMBytecode(bytecode); + + if (getMarker(hash) == 0) { + // ToDO: use efficient call + L1_MESSENGER_CONTRACT.sendToL1(bytecode); + + assembly { + sstore(hash, 1) + } + } + } } diff --git a/system-contracts/contracts/L1Messenger.sol b/system-contracts/contracts/L1Messenger.sol index 2b584d110..ccaf42a1c 100644 --- a/system-contracts/contracts/L1Messenger.sol +++ b/system-contracts/contracts/L1Messenger.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IL1Messenger, L2ToL1Log, L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH, L2_TO_L1_LOG_SERIALIZE_SIZE, STATE_DIFF_COMPRESSION_VERSION_NUMBER} from "./interfaces/IL1Messenger.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/L2BaseToken.sol b/system-contracts/contracts/L2BaseToken.sol index 8101c638b..f5fcc0ece 100644 --- a/system-contracts/contracts/L2BaseToken.sol +++ b/system-contracts/contracts/L2BaseToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IBaseToken} from "./interfaces/IBaseToken.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/MsgValueSimulator.sol b/system-contracts/contracts/MsgValueSimulator.sol index c1dcde694..ed13d95b1 100644 --- a/system-contracts/contracts/MsgValueSimulator.sol +++ b/system-contracts/contracts/MsgValueSimulator.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {Utils} from "./libraries/Utils.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; diff --git a/system-contracts/contracts/NonceHolder.sol b/system-contracts/contracts/NonceHolder.sol index 12abda8bd..4c5c09d6b 100644 --- a/system-contracts/contracts/NonceHolder.sol +++ b/system-contracts/contracts/NonceHolder.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {INonceHolder} from "./interfaces/INonceHolder.sol"; import {IContractDeployer} from "./interfaces/IContractDeployer.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; -import {DEPLOYER_SYSTEM_CONTRACT} from "./Constants.sol"; +import {DEPLOYER_SYSTEM_CONTRACT, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "./Constants.sol"; /** * @author Matter Labs @@ -134,7 +134,8 @@ contract NonceHolder is INonceHolder, ISystemContract { /// @return prevDeploymentNonce The deployment nonce at the time this function is called. function incrementDeploymentNonce(address _address) external returns (uint256 prevDeploymentNonce) { require( - msg.sender == address(DEPLOYER_SYSTEM_CONTRACT), + msg.sender == address(DEPLOYER_SYSTEM_CONTRACT) || + ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender), "Only the contract deployer can increment the deployment nonce" ); uint256 addressAsKey = uint256(uint160(_address)); diff --git a/system-contracts/contracts/PubdataChunkPublisher.sol b/system-contracts/contracts/PubdataChunkPublisher.sol index 53c265e9b..eabbe540a 100644 --- a/system-contracts/contracts/PubdataChunkPublisher.sol +++ b/system-contracts/contracts/PubdataChunkPublisher.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IPubdataChunkPublisher} from "./interfaces/IPubdataChunkPublisher.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/SystemContext.sol b/system-contracts/contracts/SystemContext.sol index 51b9633d9..fcb7d7439 100644 --- a/system-contracts/contracts/SystemContext.sol +++ b/system-contracts/contracts/SystemContext.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {ISystemContext} from "./interfaces/ISystemContext.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/interfaces/IAccount.sol b/system-contracts/contracts/interfaces/IAccount.sol index c32b35767..dd88d68bf 100644 --- a/system-contracts/contracts/interfaces/IAccount.sol +++ b/system-contracts/contracts/interfaces/IAccount.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {Transaction} from "../libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/interfaces/IAccountCodeStorage.sol b/system-contracts/contracts/interfaces/IAccountCodeStorage.sol index c266774ea..6e67e82f6 100644 --- a/system-contracts/contracts/interfaces/IAccountCodeStorage.sol +++ b/system-contracts/contracts/interfaces/IAccountCodeStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; interface IAccountCodeStorage { function storeAccountConstructingCodeHash(address _address, bytes32 _hash) external; @@ -14,4 +14,6 @@ interface IAccountCodeStorage { function getCodeHash(uint256 _input) external view returns (bytes32 codeHash); function getCodeSize(uint256 _input) external view returns (uint256 codeSize); + + function isAccountEVM(address _addr) external view returns (bool); } diff --git a/system-contracts/contracts/interfaces/IBaseToken.sol b/system-contracts/contracts/interfaces/IBaseToken.sol index d15f2f123..b1dce57f0 100644 --- a/system-contracts/contracts/interfaces/IBaseToken.sol +++ b/system-contracts/contracts/interfaces/IBaseToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; interface IBaseToken { function balanceOf(uint256) external view returns (uint256); diff --git a/system-contracts/contracts/interfaces/IBootloaderUtilities.sol b/system-contracts/contracts/interfaces/IBootloaderUtilities.sol index 31413320a..ffbb8712d 100644 --- a/system-contracts/contracts/interfaces/IBootloaderUtilities.sol +++ b/system-contracts/contracts/interfaces/IBootloaderUtilities.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {Transaction} from "../libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/interfaces/IComplexUpgrader.sol b/system-contracts/contracts/interfaces/IComplexUpgrader.sol index 1b5e15182..f083d9b50 100644 --- a/system-contracts/contracts/interfaces/IComplexUpgrader.sol +++ b/system-contracts/contracts/interfaces/IComplexUpgrader.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ICompressor.sol b/system-contracts/contracts/interfaces/ICompressor.sol index 3062ea4f7..893e67214 100644 --- a/system-contracts/contracts/interfaces/ICompressor.sol +++ b/system-contracts/contracts/interfaces/ICompressor.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; // The bitmask by applying which to the compressed state diff metadata we retrieve its operation. uint8 constant OPERATION_BITMASK = 7; diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index 3f84672d7..636c804e0 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; interface IContractDeployer { /// @notice Defines the version of the account abstraction protocol @@ -40,6 +40,8 @@ interface IContractDeployer { event AccountVersionUpdated(address indexed accountAddress, AccountAbstractionVersion aaVersion); + event EVMProxyHashUpdated(bytes32 indexed oldHash, bytes32 indexed newHash); + function getNewAddressCreate2( address _sender, bytes32 _bytecodeHash, @@ -88,4 +90,16 @@ interface IContractDeployer { /// @notice Can be called by an account to update its nonce ordering function updateNonceOrdering(AccountNonceOrdering _nonceOrdering) external; + + function createEVM(bytes calldata _initCode) external payable returns (address newAddress); + + function create2EVM(bytes32 _salt, bytes calldata _initCode) external payable returns (address); + + function createEVMInternal(address _newAddress, bytes calldata _initCode) external payable; + + function evmCodeHash(address) external view returns (bytes32); + + function setDeployedCode(uint256 constructorGasLeft, bytes calldata newDeployedCode) external; + + function constructorReturnGas() external view returns (uint256); } diff --git a/system-contracts/contracts/interfaces/IImmutableSimulator.sol b/system-contracts/contracts/interfaces/IImmutableSimulator.sol index d30ac9b96..d11422d6f 100644 --- a/system-contracts/contracts/interfaces/IImmutableSimulator.sol +++ b/system-contracts/contracts/interfaces/IImmutableSimulator.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; struct ImmutableData { uint256 index; diff --git a/system-contracts/contracts/interfaces/IKnownCodesStorage.sol b/system-contracts/contracts/interfaces/IKnownCodesStorage.sol index 98a1277d0..1be6f1b3e 100644 --- a/system-contracts/contracts/interfaces/IKnownCodesStorage.sol +++ b/system-contracts/contracts/interfaces/IKnownCodesStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs @@ -16,4 +16,6 @@ interface IKnownCodesStorage { function markBytecodeAsPublished(bytes32 _bytecodeHash) external; function getMarker(bytes32 _hash) external view returns (uint256); + + function publishEVMBytecode(bytes calldata bytecode) external; } diff --git a/system-contracts/contracts/interfaces/IL1Messenger.sol b/system-contracts/contracts/interfaces/IL1Messenger.sol index cd0cc90f7..d8c4342da 100644 --- a/system-contracts/contracts/interfaces/IL1Messenger.sol +++ b/system-contracts/contracts/interfaces/IL1Messenger.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /// @dev The log passed from L2 /// @param l2ShardId The shard identifier, 0 - rollup, 1 - porter. All other values are not used but are reserved for the future diff --git a/system-contracts/contracts/interfaces/IL2StandardToken.sol b/system-contracts/contracts/interfaces/IL2StandardToken.sol index 3d75c8ede..6af08d410 100644 --- a/system-contracts/contracts/interfaces/IL2StandardToken.sol +++ b/system-contracts/contracts/interfaces/IL2StandardToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; interface IL2StandardToken { event BridgeMint(address indexed _account, uint256 _amount); diff --git a/system-contracts/contracts/interfaces/IMailbox.sol b/system-contracts/contracts/interfaces/IMailbox.sol index ba673058c..1e263a2bb 100644 --- a/system-contracts/contracts/interfaces/IMailbox.sol +++ b/system-contracts/contracts/interfaces/IMailbox.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; interface IMailbox { function finalizeEthWithdrawal( diff --git a/system-contracts/contracts/interfaces/INonceHolder.sol b/system-contracts/contracts/interfaces/INonceHolder.sol index 1213fbea4..2719ff8ca 100644 --- a/system-contracts/contracts/interfaces/INonceHolder.sol +++ b/system-contracts/contracts/interfaces/INonceHolder.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/IPaymaster.sol b/system-contracts/contracts/interfaces/IPaymaster.sol index 7b06d86ee..6cb43249f 100644 --- a/system-contracts/contracts/interfaces/IPaymaster.sol +++ b/system-contracts/contracts/interfaces/IPaymaster.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {Transaction} from "../libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/interfaces/IPaymasterFlow.sol b/system-contracts/contracts/interfaces/IPaymasterFlow.sol index 38866073e..e2ceb7117 100644 --- a/system-contracts/contracts/interfaces/IPaymasterFlow.sol +++ b/system-contracts/contracts/interfaces/IPaymasterFlow.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol b/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol index 83c1893fd..4f781add6 100644 --- a/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol +++ b/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ISystemContext.sol b/system-contracts/contracts/interfaces/ISystemContext.sol index a122a04f5..2ce5085f5 100644 --- a/system-contracts/contracts/interfaces/ISystemContext.sol +++ b/system-contracts/contracts/interfaces/ISystemContext.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol b/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol index a44b61b23..954d4b5e8 100644 --- a/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol +++ b/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ISystemContract.sol b/system-contracts/contracts/interfaces/ISystemContract.sol index 01ff9d95f..f57d00f1e 100644 --- a/system-contracts/contracts/interfaces/ISystemContract.sol +++ b/system-contracts/contracts/interfaces/ISystemContract.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {SystemContractHelper} from "../libraries/SystemContractHelper.sol"; import {BOOTLOADER_FORMAL_ADDRESS, FORCE_DEPLOYER} from "../Constants.sol"; diff --git a/system-contracts/contracts/libraries/EfficientCall.sol b/system-contracts/contracts/libraries/EfficientCall.sol index 8f9939f08..b4994cc44 100644 --- a/system-contracts/contracts/libraries/EfficientCall.sol +++ b/system-contracts/contracts/libraries/EfficientCall.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {SystemContractHelper, ADDRESS_MASK} from "./SystemContractHelper.sol"; import {SystemContractsCaller, CalldataForwardingMode, RAW_FAR_CALL_BY_REF_CALL_ADDRESS, SYSTEM_CALL_BY_REF_CALL_ADDRESS, MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT, MIMIC_CALL_BY_REF_CALL_ADDRESS} from "./SystemContractsCaller.sol"; diff --git a/system-contracts/contracts/libraries/RLPEncoder.sol b/system-contracts/contracts/libraries/RLPEncoder.sol index 8e32ea9ba..454bb4316 100644 --- a/system-contracts/contracts/libraries/RLPEncoder.sol +++ b/system-contracts/contracts/libraries/RLPEncoder.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/libraries/SystemContractHelper.sol b/system-contracts/contracts/libraries/SystemContractHelper.sol index 7ae75b520..ae8b391a4 100644 --- a/system-contracts/contracts/libraries/SystemContractHelper.sol +++ b/system-contracts/contracts/libraries/SystemContractHelper.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {MAX_SYSTEM_CONTRACT_ADDRESS} from "../Constants.sol"; +import {Utils} from "./Utils.sol"; -import {CALLFLAGS_CALL_ADDRESS, CODE_ADDRESS_CALL_ADDRESS, EVENT_WRITE_ADDRESS, EVENT_INITIALIZE_ADDRESS, GET_EXTRA_ABI_DATA_ADDRESS, LOAD_CALLDATA_INTO_ACTIVE_PTR_CALL_ADDRESS, META_CODE_SHARD_ID_OFFSET, META_CALLER_SHARD_ID_OFFSET, META_SHARD_ID_OFFSET, META_AUX_HEAP_SIZE_OFFSET, META_HEAP_SIZE_OFFSET, META_PUBDATA_PUBLISHED_OFFSET, META_CALL_ADDRESS, PTR_CALLDATA_CALL_ADDRESS, PTR_ADD_INTO_ACTIVE_CALL_ADDRESS, PTR_SHRINK_INTO_ACTIVE_CALL_ADDRESS, PTR_PACK_INTO_ACTIVE_CALL_ADDRESS, PRECOMPILE_CALL_ADDRESS, SET_CONTEXT_VALUE_CALL_ADDRESS, TO_L1_CALL_ADDRESS} from "./SystemContractsCaller.sol"; +import {SystemContractsCaller, CalldataForwardingMode, CALLFLAGS_CALL_ADDRESS, CODE_ADDRESS_CALL_ADDRESS, EVENT_WRITE_ADDRESS, EVENT_INITIALIZE_ADDRESS, GET_EXTRA_ABI_DATA_ADDRESS, LOAD_CALLDATA_INTO_ACTIVE_PTR_CALL_ADDRESS, META_CODE_SHARD_ID_OFFSET, META_CALLER_SHARD_ID_OFFSET, META_SHARD_ID_OFFSET, META_AUX_HEAP_SIZE_OFFSET, META_HEAP_SIZE_OFFSET, META_PUBDATA_PUBLISHED_OFFSET, META_CALL_ADDRESS, PTR_CALLDATA_CALL_ADDRESS, PTR_ADD_INTO_ACTIVE_CALL_ADDRESS, PTR_SHRINK_INTO_ACTIVE_CALL_ADDRESS, PTR_PACK_INTO_ACTIVE_CALL_ADDRESS, PRECOMPILE_CALL_ADDRESS, SET_CONTEXT_VALUE_CALL_ADDRESS, TO_L1_CALL_ADDRESS, MIMIC_CALL_CALL_ADDRESS, PTR_DATA_SIZE, PTR_DATA_COPY, LOAD_LATEST_RETURNDATA_INTO_ACTIVE_PTR_CALL_ADDRESS} from "./SystemContractsCaller.sol"; uint256 constant UINT32_MASK = type(uint32).max; uint256 constant UINT64_MASK = type(uint64).max; @@ -352,4 +353,62 @@ library SystemContractHelper { ); require(precompileCallSuccess, "Failed to charge gas"); } + + function mimicCall( + uint32 gasLimit, + address to, + address whoToMimic, + bytes memory data, + bool isConstructorCall, + bool isSystemCall + ) internal returns (bool success) { + address callAddr = MIMIC_CALL_CALL_ADDRESS; + + uint32 dataStart; + assembly { + dataStart := add(data, 0x20) + } + uint32 dataLength = uint32(Utils.safeCastToU32(data.length)); + + uint256 farCallAbi = SystemContractsCaller.getFarCallABI( + 0, + 0, + dataStart, + dataLength, + gasLimit, + // Only rollup is supported for now + 0, + CalldataForwardingMode.UseHeap, + isConstructorCall, + isSystemCall + ); + + // Doing the system call directly + assembly { + success := call(to, callAddr, 0, farCallAbi, whoToMimic, 0, 0) + } + } + + function getActivePtrDataSize() internal view returns (uint256 size) { + address callAddr = PTR_DATA_SIZE; + + assembly { + size := staticcall(0, callAddr, 0, 0xFFFF, 0, 0) + } + } + + function copyActivePtrData(uint256 _dest, uint256 _source, uint256 _size) internal view { + address callAddr = PTR_DATA_COPY; + + assembly { + pop(staticcall(_dest, callAddr, _source, _size, 0, 0)) + } + } + + function loadReturndataIntoActivePtr() internal view { + address callAddr = LOAD_LATEST_RETURNDATA_INTO_ACTIVE_PTR_CALL_ADDRESS; + assembly { + pop(staticcall(0, callAddr, 0, 0xFFFF, 0, 0)) + } + } } diff --git a/system-contracts/contracts/libraries/SystemContractsCaller.sol b/system-contracts/contracts/libraries/SystemContractsCaller.sol index d964fbbe7..dccca09af 100644 --- a/system-contracts/contracts/libraries/SystemContractsCaller.sol +++ b/system-contracts/contracts/libraries/SystemContractsCaller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {MSG_VALUE_SYSTEM_CONTRACT, MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT} from "../Constants.sol"; import {Utils} from "./Utils.sol"; @@ -37,6 +37,10 @@ address constant PTR_PACK_INTO_ACTIVE_CALL_ADDRESS = address((1 << 16) - 25); address constant MULTIPLICATION_HIGH_ADDRESS = address((1 << 16) - 26); address constant GET_EXTRA_ABI_DATA_ADDRESS = address((1 << 16) - 27); +address constant PTR_DATA_LOAD = address((1 << 16) - 28); +address constant PTR_DATA_COPY = address((1 << 16) - 29); +address constant PTR_DATA_SIZE = address((1 << 16) - 30); + // All the offsets are in bits uint256 constant META_PUBDATA_PUBLISHED_OFFSET = 0 * 8; uint256 constant META_HEAP_SIZE_OFFSET = 8 * 8; diff --git a/system-contracts/contracts/libraries/TransactionHelper.sol b/system-contracts/contracts/libraries/TransactionHelper.sol index 9a2921010..7a8ab011a 100644 --- a/system-contracts/contracts/libraries/TransactionHelper.sol +++ b/system-contracts/contracts/libraries/TransactionHelper.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IERC20} from "../openzeppelin/token/ERC20/IERC20.sol"; import {SafeERC20} from "../openzeppelin/token/ERC20/utils/SafeERC20.sol"; @@ -161,7 +161,9 @@ library TransactionHelper { encodedGasParam = bytes.concat(encodedGasPrice, encodedGasLimit); } - bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); + bytes memory encodedTo = _transaction.reserved[1] == 0 + ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) + : bytes(hex"80"); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // Encode only the length of the transaction data, and not the data itself, // so as not to copy to memory a potentially huge transaction data twice. @@ -230,7 +232,9 @@ library TransactionHelper { bytes memory encodedNonce = RLPEncoder.encodeUint256(_transaction.nonce); bytes memory encodedGasPrice = RLPEncoder.encodeUint256(_transaction.maxFeePerGas); bytes memory encodedGasLimit = RLPEncoder.encodeUint256(_transaction.gasLimit); - bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); + bytes memory encodedTo = _transaction.reserved[1] == 0 + ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) + : bytes(hex"80"); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // solhint-disable-next-line func-named-parameters encodedFixedLengthParams = bytes.concat( @@ -303,7 +307,9 @@ library TransactionHelper { bytes memory encodedMaxPriorityFeePerGas = RLPEncoder.encodeUint256(_transaction.maxPriorityFeePerGas); bytes memory encodedMaxFeePerGas = RLPEncoder.encodeUint256(_transaction.maxFeePerGas); bytes memory encodedGasLimit = RLPEncoder.encodeUint256(_transaction.gasLimit); - bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); + bytes memory encodedTo = _transaction.reserved[1] == 0 + ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) + : bytes(hex"80"); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // solhint-disable-next-line func-named-parameters encodedFixedLengthParams = bytes.concat( diff --git a/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol b/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol index 4ce65f5fb..e61378d4c 100644 --- a/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol +++ b/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/libraries/Utils.sol b/system-contracts/contracts/libraries/Utils.sol index 5fa7eec6f..47172f62a 100644 --- a/system-contracts/contracts/libraries/Utils.sol +++ b/system-contracts/contracts/libraries/Utils.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {EfficientCall} from "./EfficientCall.sol"; +import {RLPEncoder} from "./RLPEncoder.sol"; /** * @author Matter Labs @@ -35,9 +36,23 @@ library Utils { return uint24(_x); } + function isCodeHashEVM(bytes32 _bytecodeHash) internal pure returns (bool) { + // TODO: use constants for that + return (uint8(_bytecodeHash[0]) == 2); + } + /// @return codeLength The bytecode length in bytes function bytecodeLenInBytes(bytes32 _bytecodeHash) internal pure returns (uint256 codeLength) { - codeLength = bytecodeLenInWords(_bytecodeHash) << 5; // _bytecodeHash * 32 + // TODO: use constants for that + + if (uint8(_bytecodeHash[0]) == 1) { + codeLength = bytecodeLenInWords(_bytecodeHash) << 5; // _bytecodeHash * 32 + } else if (uint8(_bytecodeHash[0]) == 2) { + // TODO: maybe rename the function + codeLength = bytecodeLenInWords(_bytecodeHash); + } else { + codeLength = 0; + } } /// @return codeLengthInWords The bytecode length in machine words @@ -94,4 +109,48 @@ library Utils { // Setting the length hashedBytecode = hashedBytecode | bytes32(lengthInWords << 224); } + + // the real max supported number is 2^16, but we'll stick to evm convention + uint256 constant MAX_EVM_BYTECODE_LENGTH = (2 ** 16) - 1; + + function hashEVMBytecode(bytes memory _bytecode) internal view returns (bytes32 hashedEVMBytecode) { + require(_bytecode.length <= MAX_EVM_BYTECODE_LENGTH, "po"); + + hashedEVMBytecode = sha256(_bytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + + // Setting the version of the hash + hashedEVMBytecode = (hashedEVMBytecode | bytes32(uint256(2 << 248))); + hashedEVMBytecode = hashedEVMBytecode | bytes32(_bytecode.length << 224); + } + + /// @notice Calculates the address of a deployed contract via create2 on the EVM + /// @param _sender The account that deploys the contract. + /// @param _salt The create2 salt. + /// @param _bytecodeHash The hash of the init code of the new contract. + /// @return newAddress The derived address of the account. + function getNewAddressCreate2EVM( + address _sender, + bytes32 _salt, + bytes32 _bytecodeHash + ) internal pure returns (address newAddress) { + bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), _sender, _salt, _bytecodeHash)); + + newAddress = address(uint160(uint256(hash))); + } + + /// @notice Calculates the address of a deployed contract via create + /// @param _sender The account that deploys the contract. + /// @param _senderNonce The deploy nonce of the sender's account. + function getNewAddressCreateEVM(address _sender, uint256 _senderNonce) internal pure returns (address newAddress) { + bytes memory addressEncoded = RLPEncoder.encodeAddress(_sender); + bytes memory nonceEncoded = RLPEncoder.encodeUint256(_senderNonce); + + uint256 listLength = addressEncoded.length + nonceEncoded.length; + bytes memory listLengthEncoded = RLPEncoder.encodeListLen(uint64(listLength)); + + bytes memory digest = bytes.concat(listLengthEncoded, addressEncoded, nonceEncoded); + + bytes32 hash = keccak256(digest); + newAddress = address(uint160(uint256(hash))); + } } diff --git a/system-contracts/contracts/precompiles/CodeOracle.yul b/system-contracts/contracts/precompiles/CodeOracle.yul index 820b8df70..836320bda 100644 --- a/system-contracts/contracts/precompiles/CodeOracle.yul +++ b/system-contracts/contracts/precompiles/CodeOracle.yul @@ -27,14 +27,14 @@ object "CodeOracle" { //////////////////////////////////////////////////////////////// // HELPER FUNCTIONS //////////////////////////////////////////////////////////////// - + /// @notice The function that returns whether a certain versioned hash is marked as `known` /// @param versionedHash The versioned hash to check /// @return Whether the versioned hash is known function isCodeHashKnown(versionedHash) -> ret { - // 1. Selector for `KnownCodesStorage.getMarker(bytes32)` + // 1. Selector for `KnwonCodesStorage.getMarker(bytes32)` mstore(0, 0x4c6314f000000000000000000000000000000000000000000000000000000000) - // 2. Input for `KnownCodesStorage.getMarker(bytes32)` + // 2. Input for `KnwonCodesStorage.getMarker(bytes32)` mstore(4, versionedHash) let success := staticcall( @@ -66,7 +66,7 @@ object "CodeOracle" { /// @param versionedHash The versioned hash to decommit. /// @param lenInWords The length of the data in bytes to decommit. function decommit(versionedHash, lenInWords) { - // The operation below are never expected to overflow since the `lenInWords` is at most 2 bytes long. + // The operation below are never expected to overflow since the `lenInWords` is a most 2 bytes long. let gasCost := mul(decommmitCostPerWord(), lenInWords) // The cost of the decommit operation can not exceed the maximum value of the `uint32` type. @@ -88,7 +88,7 @@ object "CodeOracle" { // Decommitment failed revert(0,0) } - + // The "real" result of the `decommit` operation is a pointer to the memory page where the data was unpacked. // We do not know whether the data was unpacked into the memory of this contract or not. // @@ -96,13 +96,13 @@ object "CodeOracle" { // decommit operation into the `active` pointer. verbatim_0i_0o("decommit_ptr_to_active") - // This operation is never expected to overflow since the `lenInWords` is at most 2 bytes long. + // This operation is never expected to overflow since the `lenInWords` is a most 2 bytes long. let lenInBytes := mul(lenInWords, 32) // To avoid the complexity of calculating the length of the preimage in circuits, the length of the pointer is always fixed to 2^21 bytes. // So the amount of data actually copied is determined here. // Note, that here we overwrite the first `lenInBytes` bytes of the memory, but it is fine since the written values are equivalent - // to the bytes previously written there by the `decommit` operation (in case this is the first page where the decommit happened). + // to the bytes previously written there by the `decommit` operation (in case this is the first page where the decomit happened). // In the future we won't do this and simply return the pointer returned by the `decommit` operation, shrunk to the `lenInBytes` length. verbatim_3i_0o("active_ptr_data_copy", 0, 0, lenInBytes) @@ -127,9 +127,15 @@ object "CodeOracle" { // - hash[1] -- whether the contract is being constructed // - hash[2..3] -- big endian length of the bytecode in 32-byte words. This number must be odd. // - hash[4..31] -- the last 28 bytes of the sha256 hash. + // 2. EVM bytecode. It has the following format: + // - hash[0] -- version (0x02) + // - hash[1] -- whether the contract is being constructed + // - hash[2..3] -- big endian length of the bytecode in bytes. This number can be arbitrary. + // - hash[4..31] -- the last 28 bytes of the sha256 hash. // - // Note, that in theory it can represent just some random blob of bytes, while - // in practice it only represents only the corresponding bytecodes. + // Note, that in theory both values can represent just some random blob of bytes, while + // in practice they only represent only the corresponding bytecodes. + switch version case 1 { @@ -138,6 +144,14 @@ object "CodeOracle" { let lengthInWords := and(shr(224, versionedCodeHash), 0xffff) decommit(versionedCodeHash, lengthInWords) } + case 2 { + // We do not double check whether the length is 32 mod 64, since it assumed that only valid bytecodes + // can pass the `isCodeHashKnown` check. + let lengthInBytes := and(shr(224, versionedCodeHash), 0xffff) + + // It is assumed that the `lengthInBytes` is divisible by 32. + decommit(versionedCodeHash, div(lengthInBytes, 32)) + } default { // Unsupported revert(0,0) diff --git a/system-contracts/contracts/test-contracts/Deployable.sol b/system-contracts/contracts/test-contracts/Deployable.sol index be35861a4..677b21379 100644 --- a/system-contracts/contracts/test-contracts/Deployable.sol +++ b/system-contracts/contracts/test-contracts/Deployable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; contract Deployable { event Deployed(uint256 value, bytes data); diff --git a/system-contracts/contracts/test-contracts/GasBoundCallerTester.sol b/system-contracts/contracts/test-contracts/GasBoundCallerTester.sol index 351a55f46..509d10c09 100644 --- a/system-contracts/contracts/test-contracts/GasBoundCallerTester.sol +++ b/system-contracts/contracts/test-contracts/GasBoundCallerTester.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {GasBoundCaller} from "../GasBoundCaller.sol"; import {SystemContractHelper} from "../libraries/SystemContractHelper.sol"; diff --git a/system-contracts/contracts/test-contracts/MockContract.sol b/system-contracts/contracts/test-contracts/MockContract.sol index 1505be34c..f6419fb55 100644 --- a/system-contracts/contracts/test-contracts/MockContract.sol +++ b/system-contracts/contracts/test-contracts/MockContract.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; contract MockContract { event Called(uint256 value, bytes data); diff --git a/system-contracts/contracts/test-contracts/SystemCaller.sol b/system-contracts/contracts/test-contracts/SystemCaller.sol index a377174ae..119afe08a 100644 --- a/system-contracts/contracts/test-contracts/SystemCaller.sol +++ b/system-contracts/contracts/test-contracts/SystemCaller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {SYSTEM_CALL_CALL_ADDRESS, MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT, SystemContractsCaller, CalldataForwardingMode} from "../libraries/SystemContractsCaller.sol"; import {Utils} from "../libraries/Utils.sol"; diff --git a/system-contracts/hardhat.config.ts b/system-contracts/hardhat.config.ts index cc0a5e0b4..a193d445b 100644 --- a/system-contracts/hardhat.config.ts +++ b/system-contracts/hardhat.config.ts @@ -33,8 +33,9 @@ export default { ethNetwork: "http://localhost:8545", }, solidity: { - version: "0.8.20", + version: "0.8.24", settings: { + evmVersion: "cancun", optimizer: { enabled: true, runs: 9999999, diff --git a/yarn.lock b/yarn.lock index 2c64e92e6..14c214541 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6028,7 +6028,7 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.22.4, resolve@^1.8.1: +resolve@^1.1.6, resolve@^1.22.4, resolve@^1.8.1: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== From aa30514b6f99b4849937fe632abc80dd807e7dc7 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Fri, 9 Aug 2024 11:01:35 -0300 Subject: [PATCH 02/59] fmt --- system-contracts/contracts/ContractDeployer.sol | 2 +- system-contracts/contracts/libraries/SystemContractHelper.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index e23f2a388..5e675260a 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import {ImmutableData} from "./interfaces/IImmutableSimulator.sol"; import {IContractDeployer} from "./interfaces/IContractDeployer.sol"; -import {CREATE2_EVM_PREFIX, CREATE2_PREFIX, CREATE_PREFIX, NONCE_HOLDER_SYSTEM_CONTRACT, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT, FORCE_DEPLOYER, MAX_SYSTEM_CONTRACT_ADDRESS, KNOWN_CODE_STORAGE_CONTRACT, BASE_TOKEN_SYSTEM_CONTRACT , IMMUTABLE_SIMULATOR_SYSTEM_CONTRACT, COMPLEX_UPGRADER_CONTRACT, KECCAK256_SYSTEM_CONTRACT} from "./Constants.sol"; +import {CREATE2_EVM_PREFIX, CREATE2_PREFIX, CREATE_PREFIX, NONCE_HOLDER_SYSTEM_CONTRACT, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT, FORCE_DEPLOYER, MAX_SYSTEM_CONTRACT_ADDRESS, KNOWN_CODE_STORAGE_CONTRACT, BASE_TOKEN_SYSTEM_CONTRACT, IMMUTABLE_SIMULATOR_SYSTEM_CONTRACT, COMPLEX_UPGRADER_CONTRACT, KECCAK256_SYSTEM_CONTRACT} from "./Constants.sol"; import {Utils} from "./libraries/Utils.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; diff --git a/system-contracts/contracts/libraries/SystemContractHelper.sol b/system-contracts/contracts/libraries/SystemContractHelper.sol index 0828ded13..226472fe6 100644 --- a/system-contracts/contracts/libraries/SystemContractHelper.sol +++ b/system-contracts/contracts/libraries/SystemContractHelper.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.20; import {MAX_SYSTEM_CONTRACT_ADDRESS} from "../Constants.sol"; import {Utils} from "./Utils.sol"; -import {SystemContractsCaller, CalldataForwardingMode, CALLFLAGS_CALL_ADDRESS, CODE_ADDRESS_CALL_ADDRESS, EVENT_WRITE_ADDRESS, EVENT_INITIALIZE_ADDRESS, GET_EXTRA_ABI_DATA_ADDRESS, LOAD_CALLDATA_INTO_ACTIVE_PTR_CALL_ADDRESS, META_CODE_SHARD_ID_OFFSET, META_CALLER_SHARD_ID_OFFSET, META_SHARD_ID_OFFSET, META_AUX_HEAP_SIZE_OFFSET, META_HEAP_SIZE_OFFSET, META_PUBDATA_PUBLISHED_OFFSET, META_CALL_ADDRESS, PTR_CALLDATA_CALL_ADDRESS, PTR_ADD_INTO_ACTIVE_CALL_ADDRESS, PTR_SHRINK_INTO_ACTIVE_CALL_ADDRESS, PTR_PACK_INTO_ACTIVE_CALL_ADDRESS, PRECOMPILE_CALL_ADDRESS, SET_CONTEXT_VALUE_CALL_ADDRESS, TO_L1_CALL_ADDRESS, MIMIC_CALL_CALL_ADDRESS, PTR_DATA_SIZE, PTR_DATA_COPY, LOAD_LATEST_RETURNDATA_INTO_ACTIVE_PTR_CALL_ADDRESS} from "./SystemContractsCaller.sol"; +import {SystemContractsCaller, CalldataForwardingMode, CALLFLAGS_CALL_ADDRESS, CODE_ADDRESS_CALL_ADDRESS, EVENT_WRITE_ADDRESS, EVENT_INITIALIZE_ADDRESS, GET_EXTRA_ABI_DATA_ADDRESS, LOAD_CALLDATA_INTO_ACTIVE_PTR_CALL_ADDRESS, META_CODE_SHARD_ID_OFFSET, META_CALLER_SHARD_ID_OFFSET, META_SHARD_ID_OFFSET, META_AUX_HEAP_SIZE_OFFSET, META_HEAP_SIZE_OFFSET, META_PUBDATA_PUBLISHED_OFFSET, META_CALL_ADDRESS, PTR_CALLDATA_CALL_ADDRESS, PTR_ADD_INTO_ACTIVE_CALL_ADDRESS, PTR_SHRINK_INTO_ACTIVE_CALL_ADDRESS, PTR_PACK_INTO_ACTIVE_CALL_ADDRESS, PRECOMPILE_CALL_ADDRESS, SET_CONTEXT_VALUE_CALL_ADDRESS, TO_L1_CALL_ADDRESS, MIMIC_CALL_CALL_ADDRESS, PTR_DATA_SIZE, PTR_DATA_COPY, LOAD_LATEST_RETURNDATA_INTO_ACTIVE_PTR_CALL_ADDRESS} from "./SystemContractsCaller.sol"; import {IndexOutOfBounds, FailedToChargeGas} from "../SystemContractErrors.sol"; uint256 constant UINT32_MASK = type(uint32).max; From 04f5920b6cce11dca03adaa545db6d28d54c02f6 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Fri, 9 Aug 2024 19:01:37 -0300 Subject: [PATCH 03/59] Update support for evm simulator with latest changes --- .../dev-contracts/test/CustomUpgradeTest.sol | 2 +- .../test/ExecutorProvingTest.sol | 3 +- .../StateTransitionManager.sol | 1 + .../chain-deps/DiamondInit.sol | 1 + .../chain-deps/ZkSyncHyperchainStorage.sol | 3 + .../chain-deps/facets/Executor.sol | 3 +- .../chain-deps/facets/Getters.sol | 5 ++ .../chain-interfaces/IDiamondInit.sol | 2 + .../chain-interfaces/IGetters.sol | 3 + .../contracts/upgrades/BaseZkSyncUpgrade.sol | 28 ++++++- l1-contracts/deploy-scripts/DeployL1.s.sol | 2 + .../scripts/upgrade-consistency-checker.ts | 11 ++- l1-contracts/src.ts/deploy-process.ts | 2 + l1-contracts/src.ts/deploy-test-process.ts | 2 + l1-contracts/src.ts/deploy.ts | 2 + l1-contracts/src.ts/diamondCut.ts | 1 + l1-contracts/src.ts/utils.ts | 7 ++ .../concrete/DiamondCut/UpgradeLogic.t.sol | 1 + .../concrete/Executor/ExecutorProof.t.sol | 7 +- .../concrete/Executor/_Executor_Shared.t.sol | 28 ++++--- .../foundry/unit/concrete/Utils/Utils.sol | 79 ++++++++++--------- .../unit/concrete/Utils/UtilsFacet.sol | 8 ++ .../chain-deps/DiamondInit/Initialize.t.sol | 1 + .../facets/Getters/_Getters_Shared.t.sol | 4 + .../test/unit_tests/l2-upgrade.test.spec.ts | 4 + .../test/unit_tests/proxy_test.spec.ts | 1 + system-contracts/scripts/deploy-preimages.ts | 55 +++++++++++++ 27 files changed, 207 insertions(+), 59 deletions(-) diff --git a/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol b/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol index 7055ce557..317c531bd 100644 --- a/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol +++ b/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol @@ -31,7 +31,7 @@ contract CustomUpgradeTest is BaseZkSyncUpgrade { (uint32 newMinorVersion, bool isPatchOnly) = _setNewProtocolVersion(_proposedUpgrade.newProtocolVersion); _upgradeL1Contract(_proposedUpgrade.l1ContractsUpgradeCalldata); _upgradeVerifier(_proposedUpgrade.verifier, _proposedUpgrade.verifierParams); - _setBaseSystemContracts(_proposedUpgrade.bootloaderHash, _proposedUpgrade.defaultAccountHash, isPatchOnly); + _setBaseSystemContracts(_proposedUpgrade.bootloaderHash, _proposedUpgrade.defaultAccountHash, _proposedUpgrade.evmSimulatorHash, isPatchOnly); bytes32 txHash; txHash = _setL2SystemContractUpgrade( diff --git a/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol b/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol index 50bccb744..adc528751 100644 --- a/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol +++ b/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol @@ -33,9 +33,10 @@ contract ExecutorProvingTest is ExecutorFacet { } /// Sets the DefaultAccount Hash and Bootloader Hash. - function setHashes(bytes32 l2DefaultAccountBytecodeHash, bytes32 l2BootloaderBytecodeHash) external { + function setHashes(bytes32 l2DefaultAccountBytecodeHash, bytes32 l2BootloaderBytecodeHash, bytes32 l2EvmSimulatorBytecode) external { s.l2DefaultAccountBytecodeHash = l2DefaultAccountBytecodeHash; s.l2BootloaderBytecodeHash = l2BootloaderBytecodeHash; + s.l2EvmSimulatorBytecodeHash = l2EvmSimulatorBytecode; s.zkPorterIsAvailable = false; } } diff --git a/l1-contracts/contracts/state-transition/StateTransitionManager.sol b/l1-contracts/contracts/state-transition/StateTransitionManager.sol index 9ac15cf19..5f286520c 100644 --- a/l1-contracts/contracts/state-transition/StateTransitionManager.sol +++ b/l1-contracts/contracts/state-transition/StateTransitionManager.sol @@ -343,6 +343,7 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own factoryDeps: bytesEmptyArray, bootloaderHash: bytes32(0), defaultAccountHash: bytes32(0), + evmSimulatorHash: bytes32(0), verifier: address(0), verifierParams: VerifierParams({ recursionNodeLevelVkHash: bytes32(0), diff --git a/l1-contracts/contracts/state-transition/chain-deps/DiamondInit.sol b/l1-contracts/contracts/state-transition/chain-deps/DiamondInit.sol index 145056590..3593850b3 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/DiamondInit.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/DiamondInit.sol @@ -45,6 +45,7 @@ contract DiamondInit is ZkSyncHyperchainBase, IDiamondInit { s.__DEPRECATED_verifierParams = _initializeData.verifierParams; s.l2BootloaderBytecodeHash = _initializeData.l2BootloaderBytecodeHash; s.l2DefaultAccountBytecodeHash = _initializeData.l2DefaultAccountBytecodeHash; + s.l2EvmSimulatorBytecodeHash = _initializeData.l2EvmSimulatorBytecodeHash; s.priorityTxMaxGasLimit = _initializeData.priorityTxMaxGasLimit; s.feeParams = _initializeData.feeParams; s.blobVersionedHashRetriever = _initializeData.blobVersionedHashRetriever; diff --git a/l1-contracts/contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol b/l1-contracts/contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol index a06921fdb..b490d2f62 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol @@ -98,6 +98,9 @@ struct ZkSyncHyperchainStorage { /// @notice Bytecode hash of default account (bytecode for EOA). /// @dev Used as an input to zkp-circuit. bytes32 l2DefaultAccountBytecodeHash; + /// @notice Bytecode hash of evm simulator. + /// @dev Used as an input to zkp-circuit. + bytes32 l2EvmSimulatorBytecodeHash; /// @dev Indicates that the porter may be touched on L2 transactions. /// @dev Used as an input to zkp-circuit. bool zkPorterIsAvailable; diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol index 217e08a1a..a5c165296 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol @@ -519,13 +519,14 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { function _batchMetaParameters() internal view returns (bytes memory) { bytes32 l2DefaultAccountBytecodeHash = s.l2DefaultAccountBytecodeHash; + bytes32 l2EvmSimulatorBytecodeHash = s.l2EvmSimulatorBytecodeHash; return abi.encodePacked( s.zkPorterIsAvailable, s.l2BootloaderBytecodeHash, l2DefaultAccountBytecodeHash, // VM 1.5.0 requires us to pass the EVM simulator code hash. For now it is the same as the default account. - l2DefaultAccountBytecodeHash + l2EvmSimulatorBytecodeHash ); } diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol index 77800ed12..2465c6935 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol @@ -137,6 +137,11 @@ contract GettersFacet is ZkSyncHyperchainBase, IGetters, ILegacyGetters { return s.l2DefaultAccountBytecodeHash; } + /// @inheritdoc IGetters + function getL2EvmSimulatorBytecodeHash() external view returns (bytes32) { + return s.l2EvmSimulatorBytecodeHash; + } + /// @inheritdoc IGetters function getVerifierParams() external view returns (VerifierParams memory) { return s.__DEPRECATED_verifierParams; diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IDiamondInit.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IDiamondInit.sol index a8209b546..467638c3c 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IDiamondInit.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IDiamondInit.sol @@ -36,6 +36,7 @@ struct InitializeData { VerifierParams verifierParams; bytes32 l2BootloaderBytecodeHash; bytes32 l2DefaultAccountBytecodeHash; + bytes32 l2EvmSimulatorBytecodeHash; uint256 priorityTxMaxGasLimit; FeeParams feeParams; address blobVersionedHashRetriever; @@ -53,6 +54,7 @@ struct InitializeDataNewChain { VerifierParams verifierParams; bytes32 l2BootloaderBytecodeHash; bytes32 l2DefaultAccountBytecodeHash; + bytes32 l2EvmSimulatorBytecodeHash; uint256 priorityTxMaxGasLimit; FeeParams feeParams; address blobVersionedHashRetriever; diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol index 9d77efdf3..85dab6950 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol @@ -78,6 +78,9 @@ interface IGetters is IZkSyncHyperchainBase { /// @return Bytecode hash of default account (bytecode for EOA). function getL2DefaultAccountBytecodeHash() external view returns (bytes32); + /// @return Bytecode hash of EVM simulator. + function getL2EvmSimulatorBytecodeHash() external view returns (bytes32); + /// @return Verifier parameters. /// @dev This function is deprecated and will soon be removed. function getVerifierParams() external view returns (VerifierParams memory); diff --git a/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol b/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol index 6510a2b7d..20c897fdb 100644 --- a/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol +++ b/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol @@ -33,6 +33,7 @@ struct ProposedUpgrade { bytes[] factoryDeps; bytes32 bootloaderHash; bytes32 defaultAccountHash; + bytes32 evmSimulatorHash; address verifier; VerifierParams verifierParams; bytes l1ContractsUpgradeCalldata; @@ -54,6 +55,8 @@ abstract contract BaseZkSyncUpgrade is ZkSyncHyperchainBase { /// @notice Сhanges to the bytecode that is used in L2 as a default account event NewL2DefaultAccountBytecodeHash(bytes32 indexed previousBytecodeHash, bytes32 indexed newBytecodeHash); + event NewL2EvmSimulatorBytecodeHash(bytes32 indexed previousBytecodeHash, bytes32 indexed newBytecodeHash); + /// @notice Verifier address changed event NewVerifier(address indexed oldVerifier, address indexed newVerifier); @@ -77,7 +80,7 @@ abstract contract BaseZkSyncUpgrade is ZkSyncHyperchainBase { (uint32 newMinorVersion, bool isPatchOnly) = _setNewProtocolVersion(_proposedUpgrade.newProtocolVersion); _upgradeL1Contract(_proposedUpgrade.l1ContractsUpgradeCalldata); _upgradeVerifier(_proposedUpgrade.verifier, _proposedUpgrade.verifierParams); - _setBaseSystemContracts(_proposedUpgrade.bootloaderHash, _proposedUpgrade.defaultAccountHash, isPatchOnly); + _setBaseSystemContracts(_proposedUpgrade.bootloaderHash, _proposedUpgrade.defaultAccountHash, _proposedUpgrade.evmSimulatorHash, isPatchOnly); txHash = _setL2SystemContractUpgrade( _proposedUpgrade.l2ProtocolUpgradeTx, @@ -111,6 +114,26 @@ abstract contract BaseZkSyncUpgrade is ZkSyncHyperchainBase { emit NewL2DefaultAccountBytecodeHash(previousDefaultAccountBytecodeHash, _l2DefaultAccountBytecodeHash); } + /// @notice Change default account bytecode hash, that is used on L2 + /// @param _l2EvmSimulatorBytecodeHash The hash of default account L2 bytecode + /// @param _patchOnly Whether only the patch part of the protocol version semver has changed + function _setL2EvmSimulatorBytecodeHash(bytes32 _l2EvmSimulatorBytecodeHash, bool _patchOnly) private { + if (_l2EvmSimulatorBytecodeHash == bytes32(0)) { + return; + } + + require(!_patchOnly, "Patch only upgrade can not set new default account"); + + L2ContractHelper.validateBytecodeHash(_l2EvmSimulatorBytecodeHash); + + // Save previous value into the stack to put it into the event later + bytes32 previousL2EvmSimulatorBytecodeHash = s.l2EvmSimulatorBytecodeHash; + + // Change the default account bytecode hash + s.l2EvmSimulatorBytecodeHash = _l2EvmSimulatorBytecodeHash; + emit NewL2EvmSimulatorBytecodeHash(previousL2EvmSimulatorBytecodeHash, _l2EvmSimulatorBytecodeHash); + } + /// @notice Change bootloader bytecode hash, that is used on L2 /// @param _l2BootloaderBytecodeHash The hash of bootloader L2 bytecode /// @param _patchOnly Whether only the patch part of the protocol version semver has changed @@ -179,9 +202,10 @@ abstract contract BaseZkSyncUpgrade is ZkSyncHyperchainBase { /// @param _bootloaderHash The hash of the new bootloader bytecode. If zero, it will not be updated. /// @param _defaultAccountHash The hash of the new default account bytecode. If zero, it will not be updated. /// @param _patchOnly Whether only the patch part of the protocol version semver has changed. - function _setBaseSystemContracts(bytes32 _bootloaderHash, bytes32 _defaultAccountHash, bool _patchOnly) internal { + function _setBaseSystemContracts(bytes32 _bootloaderHash, bytes32 _defaultAccountHash, bytes32 _evmSimulatorHash, bool _patchOnly) internal { _setL2BootloaderBytecodeHash(_bootloaderHash, _patchOnly); _setL2DefaultAccountBytecodeHash(_defaultAccountHash, _patchOnly); + _setL2EvmSimulatorBytecodeHash(_evmSimulatorHash, _patchOnly); } /// @notice Sets the hash of the L2 system contract upgrade transaction for the next batch to be committed diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 51eb55346..db5144ad3 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -120,6 +120,7 @@ contract DeployL1Script is Script { bytes diamondCutData; bytes32 bootloaderHash; bytes32 defaultAAHash; + bytes32 evmSimulatorHash; } struct TokensConfig { @@ -435,6 +436,7 @@ contract DeployL1Script is Script { verifierParams: verifierParams, l2BootloaderBytecodeHash: config.contracts.bootloaderHash, l2DefaultAccountBytecodeHash: config.contracts.defaultAAHash, + l2EvmSimulatorBytecodeHash: config.contracts.evmSimulatorHash, priorityTxMaxGasLimit: config.contracts.priorityTxMaxGasLimit, feeParams: feeParams, blobVersionedHashRetriever: addresses.blobVersionedHashRetriever diff --git a/l1-contracts/scripts/upgrade-consistency-checker.ts b/l1-contracts/scripts/upgrade-consistency-checker.ts index 5da064a04..98e5f2c13 100644 --- a/l1-contracts/scripts/upgrade-consistency-checker.ts +++ b/l1-contracts/scripts/upgrade-consistency-checker.ts @@ -66,8 +66,9 @@ const expectedGenesisRoot = "0xabdb766b18a479a5c783a4b80e12686bc8ea3cc2d8a305049 const expectedRecursionNodeLevelVkHash = "0xf520cd5b37e74e19fdb369c8d676a04dce8a19457497ac6686d2bb95d94109c8"; const expectedRecursionLeafLevelVkHash = "0xf9664f4324c1400fa5c3822d667f30e873f53f1b8033180cd15fe41c1e2355c6"; const expectedRecursionCircuitsSetVksHash = "0x0000000000000000000000000000000000000000000000000000000000000000"; -const expectedBootloaderHash = "0x010008e742608b21bf7eb23c1a9d0602047e3618b464c9b59c0fba3b3d7ab66e"; -const expectedDefaultAccountHash = "0x01000563374c277a2c1e34659a2a1e87371bb6d852ce142022d497bfb50b9e32"; +const expectedBootloaderHash = "0x010008e7894d0dd14681c76bdb4d5e4e7f6b51bfe40c957d50eed3fec829fdb0"; +const expectedDefaultAccountHash = "0x0100058deb36e1f2eeb48bf3846d0e8eb38e9176754b73116bb41a472459a4dd"; +const expectedEvmSimulatorHash = "0x01000f197081a9906cc411d0698c4961aeb5c74877f37f7071681da6e8ef3f31"; const validatorOne = process.env.ETH_SENDER_SENDER_OPERATOR_COMMIT_ETH_ADDR!; const validatorTwo = process.env.ETH_SENDER_SENDER_OPERATOR_BLOBS_ETH_ADDR!; @@ -219,6 +220,7 @@ async function extractProxyInitializationData(contract: ethers.Contract, data: s recursionCircuitsSetVksHash, l2BootloaderBytecodeHash, l2DefaultAccountBytecodeHash, + l2EvmSimulatorBytecodeHash, // priorityTxMaxGasLimit, // // We unpack fee params @@ -238,6 +240,7 @@ async function extractProxyInitializationData(contract: ethers.Contract, data: s "bytes32", "bytes32", "bytes32", + "bytes32", "uint256", "uint256", "uint256", @@ -274,6 +277,10 @@ async function extractProxyInitializationData(contract: ethers.Contract, data: s throw new Error("L2 default account bytecode hash is not correct"); } + if (l2EvmSimulatorBytecodeHash.toLowerCase() !== expectedEvmSimulatorHash.toLowerCase()) { + throw new Error("L2 default account bytecode hash is not correct"); + } + console.log("STM init data correct!"); } diff --git a/l1-contracts/src.ts/deploy-process.ts b/l1-contracts/src.ts/deploy-process.ts index d30762a15..596e4136c 100644 --- a/l1-contracts/src.ts/deploy-process.ts +++ b/l1-contracts/src.ts/deploy-process.ts @@ -16,6 +16,8 @@ import { ADDRESS_ONE } from "../src.ts/utils"; export const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000"; export const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; +// This is the actual hash, not a placeholder like the other two. +export const L2_EVM_SIMULATOR_BYTECODE_HASH = "0x01000f197081a9906cc411d0698c4961aeb5c74877f37f7071681da6e8ef3f31"; export async function initialBridgehubDeployment( deployer: Deployer, diff --git a/l1-contracts/src.ts/deploy-test-process.ts b/l1-contracts/src.ts/deploy-test-process.ts index b8af27b34..49b26e956 100644 --- a/l1-contracts/src.ts/deploy-test-process.ts +++ b/l1-contracts/src.ts/deploy-test-process.ts @@ -15,6 +15,7 @@ import { Deployer } from "./deploy"; import { L2_BOOTLOADER_BYTECODE_HASH, L2_DEFAULT_ACCOUNT_BYTECODE_HASH, + L2_EVM_SIMULATOR_BYTECODE_HASH, initialBridgehubDeployment, registerHyperchain, } from "./deploy-process"; @@ -315,6 +316,7 @@ export class EraDeployer extends Deployer { verifierParams, l2BootloaderBytecodeHash: L2_BOOTLOADER_BYTECODE_HASH, l2DefaultAccountBytecodeHash: L2_DEFAULT_ACCOUNT_BYTECODE_HASH, + l2EvmSimulatorBytecodeHash: L2_EVM_SIMULATOR_BYTECODE_HASH, priorityTxMaxGasLimit, feeParams, blobVersionedHashRetriever: this.addresses.BlobVersionedHashRetriever, diff --git a/l1-contracts/src.ts/deploy.ts b/l1-contracts/src.ts/deploy.ts index 1e50e839f..24ac43074 100644 --- a/l1-contracts/src.ts/deploy.ts +++ b/l1-contracts/src.ts/deploy.ts @@ -40,6 +40,7 @@ import { getCurrentFacetCutsForAdd } from "./diamondCut"; import { ChainAdminFactory, ERC20Factory, StateTransitionManagerFactory } from "../typechain"; import type { Contract, Overrides } from "@ethersproject/contracts"; +import { L2_EVM_SIMULATOR_BYTECODE_HASH } from "./deploy-process"; let L2_BOOTLOADER_BYTECODE_HASH: string; let L2_DEFAULT_ACCOUNT_BYTECODE_HASH: string; @@ -105,6 +106,7 @@ export class Deployer { verifierParams, L2_BOOTLOADER_BYTECODE_HASH, L2_DEFAULT_ACCOUNT_BYTECODE_HASH, + L2_EVM_SIMULATOR_BYTECODE_HASH, this.addresses.StateTransition.Verifier, this.addresses.BlobVersionedHashRetriever, +priorityTxMaxGasLimit, diff --git a/l1-contracts/src.ts/diamondCut.ts b/l1-contracts/src.ts/diamondCut.ts index c2a8e8728..118b2c5df 100644 --- a/l1-contracts/src.ts/diamondCut.ts +++ b/l1-contracts/src.ts/diamondCut.ts @@ -35,6 +35,7 @@ export interface InitializeData { allowList: BigNumberish; l2BootloaderBytecodeHash: string; l2DefaultAccountBytecodeHash: string; + l2EvmSimulatorBytecodeHash: string, priorityTxMaxGasLimit: BigNumberish; } diff --git a/l1-contracts/src.ts/utils.ts b/l1-contracts/src.ts/utils.ts index ca18bc7e4..a5a915efd 100644 --- a/l1-contracts/src.ts/utils.ts +++ b/l1-contracts/src.ts/utils.ts @@ -187,6 +187,7 @@ function checkValidInitialCutHashParams( verifierParams: VerifierParams, l2BootloaderBytecodeHash: string, l2DefaultAccountBytecodeHash: string, + l2EvmSimulatorBytecodeHash: string, verifier: string, blobVersionedHashRetriever: string, priorityTxMaxGasLimit: number @@ -215,6 +216,9 @@ function checkValidInitialCutHashParams( if (l2DefaultAccountBytecodeHash === ethers.constants.HashZero) { throw new Error("L2 default account bytecode hash is zero"); } + if (l2EvmSimulatorBytecodeHash === ethers.constants.HashZero) { + throw new Error("L2 evm simulator bytecode hash is zero"); + } if (verifier === ethers.constants.AddressZero) { throw new Error("Verifier address is zero"); } @@ -234,6 +238,7 @@ export function compileInitialCutHash( verifierParams: VerifierParams, l2BootloaderBytecodeHash: string, l2DefaultAccountBytecodeHash: string, + l2EvmSimulatorBytecodeHash: string, verifier: string, blobVersionedHashRetriever: string, priorityTxMaxGasLimit: number, @@ -246,6 +251,7 @@ export function compileInitialCutHash( verifierParams, l2BootloaderBytecodeHash, l2DefaultAccountBytecodeHash, + l2EvmSimulatorBytecodeHash, verifier, blobVersionedHashRetriever, priorityTxMaxGasLimit @@ -279,6 +285,7 @@ export function compileInitialCutHash( verifierParams, l2BootloaderBytecodeHash, l2DefaultAccountBytecodeHash, + l2EvmSimulatorBytecodeHash, priorityTxMaxGasLimit, feeParams, blobVersionedHashRetriever, diff --git a/l1-contracts/test/foundry/unit/concrete/DiamondCut/UpgradeLogic.t.sol b/l1-contracts/test/foundry/unit/concrete/DiamondCut/UpgradeLogic.t.sol index 41c07d9a2..622cd0d1d 100644 --- a/l1-contracts/test/foundry/unit/concrete/DiamondCut/UpgradeLogic.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/DiamondCut/UpgradeLogic.t.sol @@ -90,6 +90,7 @@ contract UpgradeLogicTest is DiamondCutTest { // zkPorterIsAvailable: false, l2BootloaderBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, l2DefaultAccountBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, + l2EvmBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, priorityTxMaxGasLimit: 500000, // priority tx max L2 gas limit // initialProtocolVersion: 0, feeParams: FeeParams({ diff --git a/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol b/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol index 6c6d8a935..a4934c80e 100644 --- a/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol @@ -75,9 +75,12 @@ contract ExecutorProofTest is Test { /// This test is based on a block generated in a local system. function test_Hashes() public { utilsFacet.util_setL2DefaultAccountBytecodeHash( - 0x0100065d134a862a777e50059f5e0fbe68b583f3617a67820f7edda0d7f253a0 + 0x0100058deb36e1f2eeb48bf3846d0e8eb38e9176754b73116bb41a472459a4dd ); - utilsFacet.util_setL2BootloaderBytecodeHash(0x010009416e909e0819593a9806bbc841d25c5cdfed3f4a1523497c6814e5194a); + utilsFacet.util_setL2EvmSimulatorBytecodeHash( + 0x01000f197081a9906cc411d0698c4961aeb5c74877f37f7071681da6e8ef3f31 + ); + utilsFacet.util_setL2BootloaderBytecodeHash(0x010008e7894d0dd14681c76bdb4d5e4e7f6b51bfe40c957d50eed3fec829fdb0); utilsFacet.util_setZkPorterAvailability(false); IExecutor.CommitBatchInfo memory nextBatch = IExecutor.CommitBatchInfo({ diff --git a/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol b/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol index b96602f63..9c9c97cd0 100644 --- a/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol @@ -83,19 +83,20 @@ contract ExecutorTest is Test { selectors[12] = getters.storedBatchHash.selector; selectors[13] = getters.getL2BootloaderBytecodeHash.selector; selectors[14] = getters.getL2DefaultAccountBytecodeHash.selector; - selectors[15] = getters.getVerifierParams.selector; - selectors[16] = getters.isDiamondStorageFrozen.selector; - selectors[17] = getters.getPriorityTxMaxGasLimit.selector; - selectors[18] = getters.isEthWithdrawalFinalized.selector; - selectors[19] = getters.facets.selector; - selectors[20] = getters.facetFunctionSelectors.selector; - selectors[21] = getters.facetAddresses.selector; - selectors[22] = getters.facetAddress.selector; - selectors[23] = getters.isFunctionFreezable.selector; - selectors[24] = getters.isFacetFreezable.selector; - selectors[25] = getters.getTotalBatchesCommitted.selector; - selectors[26] = getters.getTotalBatchesVerified.selector; - selectors[27] = getters.getTotalBatchesExecuted.selector; + selectors[15] = getters.getL2EvmSimulatorBytecodeHash.selector; + selectors[16] = getters.getVerifierParams.selector; + selectors[17] = getters.isDiamondStorageFrozen.selector; + selectors[18] = getters.getPriorityTxMaxGasLimit.selector; + selectors[19] = getters.isEthWithdrawalFinalized.selector; + selectors[20] = getters.facets.selector; + selectors[21] = getters.facetFunctionSelectors.selector; + selectors[22] = getters.facetAddresses.selector; + selectors[23] = getters.facetAddress.selector; + selectors[24] = getters.isFunctionFreezable.selector; + selectors[25] = getters.isFacetFreezable.selector; + selectors[26] = getters.getTotalBatchesCommitted.selector; + selectors[27] = getters.getTotalBatchesVerified.selector; + selectors[28] = getters.getTotalBatchesExecuted.selector; return selectors; } @@ -176,6 +177,7 @@ contract ExecutorTest is Test { }), l2BootloaderBytecodeHash: dummyHash, l2DefaultAccountBytecodeHash: dummyHash, + l2EvmSimulatorBytecodeHash: dummyHash, priorityTxMaxGasLimit: 1000000, feeParams: defaultFeeParams(), blobVersionedHashRetriever: blobVersionedHashRetriever diff --git a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol index 1260334fd..595e119b2 100644 --- a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol +++ b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol @@ -226,20 +226,21 @@ library Utils { selectors[12] = GettersFacet.storedBatchHash.selector; selectors[13] = GettersFacet.getL2BootloaderBytecodeHash.selector; selectors[14] = GettersFacet.getL2DefaultAccountBytecodeHash.selector; - selectors[15] = GettersFacet.getVerifierParams.selector; - selectors[16] = GettersFacet.isDiamondStorageFrozen.selector; - selectors[17] = GettersFacet.getPriorityTxMaxGasLimit.selector; - selectors[18] = GettersFacet.isEthWithdrawalFinalized.selector; - selectors[19] = GettersFacet.facets.selector; - selectors[20] = GettersFacet.facetFunctionSelectors.selector; - selectors[21] = GettersFacet.facetAddresses.selector; - selectors[22] = GettersFacet.facetAddress.selector; - selectors[23] = GettersFacet.isFunctionFreezable.selector; - selectors[24] = GettersFacet.isFacetFreezable.selector; - selectors[25] = GettersFacet.getTotalBatchesCommitted.selector; - selectors[26] = GettersFacet.getTotalBatchesVerified.selector; - selectors[27] = GettersFacet.getTotalBatchesExecuted.selector; - selectors[28] = GettersFacet.getL2SystemContractsUpgradeTxHash.selector; + selectors[15] = GettersFacet.getL2EvmSimulatorBytecodeHash.selector; + selectors[16] = GettersFacet.getVerifierParams.selector; + selectors[17] = GettersFacet.isDiamondStorageFrozen.selector; + selectors[18] = GettersFacet.getPriorityTxMaxGasLimit.selector; + selectors[19] = GettersFacet.isEthWithdrawalFinalized.selector; + selectors[20] = GettersFacet.facets.selector; + selectors[21] = GettersFacet.facetFunctionSelectors.selector; + selectors[22] = GettersFacet.facetAddresses.selector; + selectors[23] = GettersFacet.facetAddress.selector; + selectors[24] = GettersFacet.isFunctionFreezable.selector; + selectors[25] = GettersFacet.isFacetFreezable.selector; + selectors[26] = GettersFacet.getTotalBatchesCommitted.selector; + selectors[27] = GettersFacet.getTotalBatchesVerified.selector; + selectors[28] = GettersFacet.getTotalBatchesExecuted.selector; + selectors[29] = GettersFacet.getL2SystemContractsUpgradeTxHash.selector; return selectors; } @@ -276,29 +277,31 @@ library Utils { selectors[15] = UtilsFacet.util_getL2BootloaderBytecodeHash.selector; selectors[16] = UtilsFacet.util_setL2DefaultAccountBytecodeHash.selector; selectors[17] = UtilsFacet.util_getL2DefaultAccountBytecodeHash.selector; - selectors[18] = UtilsFacet.util_setPendingAdmin.selector; - selectors[19] = UtilsFacet.util_getPendingAdmin.selector; - selectors[20] = UtilsFacet.util_setAdmin.selector; - selectors[21] = UtilsFacet.util_getAdmin.selector; - selectors[22] = UtilsFacet.util_setValidator.selector; - selectors[23] = UtilsFacet.util_getValidator.selector; - selectors[24] = UtilsFacet.util_setZkPorterAvailability.selector; - selectors[25] = UtilsFacet.util_getZkPorterAvailability.selector; - selectors[26] = UtilsFacet.util_setStateTransitionManager.selector; - selectors[27] = UtilsFacet.util_getStateTransitionManager.selector; - selectors[28] = UtilsFacet.util_setPriorityTxMaxGasLimit.selector; - selectors[29] = UtilsFacet.util_getPriorityTxMaxGasLimit.selector; - selectors[30] = UtilsFacet.util_setFeeParams.selector; - selectors[31] = UtilsFacet.util_getFeeParams.selector; - selectors[32] = UtilsFacet.util_setProtocolVersion.selector; - selectors[33] = UtilsFacet.util_getProtocolVersion.selector; - selectors[34] = UtilsFacet.util_setIsFrozen.selector; - selectors[35] = UtilsFacet.util_getIsFrozen.selector; - selectors[36] = UtilsFacet.util_setTransactionFilterer.selector; - selectors[37] = UtilsFacet.util_setBaseTokenGasPriceMultiplierDenominator.selector; - selectors[38] = UtilsFacet.util_setTotalBatchesExecuted.selector; - selectors[39] = UtilsFacet.util_setL2LogsRootHash.selector; - selectors[40] = UtilsFacet.util_setBaseTokenGasPriceMultiplierNominator.selector; + selectors[18] = UtilsFacet.util_getL2EvmSimulatorBytecodeHash.selector; + selectors[19] = UtilsFacet.util_setL2EvmSimulatorBytecodeHash.selector; + selectors[20] = UtilsFacet.util_setPendingAdmin.selector; + selectors[21] = UtilsFacet.util_getPendingAdmin.selector; + selectors[22] = UtilsFacet.util_setAdmin.selector; + selectors[23] = UtilsFacet.util_getAdmin.selector; + selectors[24] = UtilsFacet.util_setValidator.selector; + selectors[25] = UtilsFacet.util_getValidator.selector; + selectors[26] = UtilsFacet.util_setZkPorterAvailability.selector; + selectors[27] = UtilsFacet.util_getZkPorterAvailability.selector; + selectors[28] = UtilsFacet.util_setStateTransitionManager.selector; + selectors[29] = UtilsFacet.util_getStateTransitionManager.selector; + selectors[30] = UtilsFacet.util_setPriorityTxMaxGasLimit.selector; + selectors[31] = UtilsFacet.util_getPriorityTxMaxGasLimit.selector; + selectors[32] = UtilsFacet.util_setFeeParams.selector; + selectors[33] = UtilsFacet.util_getFeeParams.selector; + selectors[34] = UtilsFacet.util_setProtocolVersion.selector; + selectors[35] = UtilsFacet.util_getProtocolVersion.selector; + selectors[36] = UtilsFacet.util_setIsFrozen.selector; + selectors[37] = UtilsFacet.util_getIsFrozen.selector; + selectors[38] = UtilsFacet.util_setTransactionFilterer.selector; + selectors[39] = UtilsFacet.util_setBaseTokenGasPriceMultiplierDenominator.selector; + selectors[40] = UtilsFacet.util_setTotalBatchesExecuted.selector; + selectors[41] = UtilsFacet.util_setL2LogsRootHash.selector; + selectors[42] = UtilsFacet.util_setBaseTokenGasPriceMultiplierNominator.selector; return selectors; } @@ -339,6 +342,7 @@ library Utils { verifierParams: makeVerifierParams(), l2BootloaderBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, l2DefaultAccountBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, + l2EvmSimulatorBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, priorityTxMaxGasLimit: 500000, feeParams: makeFeeParams(), blobVersionedHashRetriever: address(0x23746765237749923040872834) @@ -354,6 +358,7 @@ library Utils { verifierParams: makeVerifierParams(), l2BootloaderBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, l2DefaultAccountBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, + l2EvmSimulatorBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, priorityTxMaxGasLimit: 80000000, feeParams: makeFeeParams(), blobVersionedHashRetriever: address(0x23746765237749923040872834) diff --git a/l1-contracts/test/foundry/unit/concrete/Utils/UtilsFacet.sol b/l1-contracts/test/foundry/unit/concrete/Utils/UtilsFacet.sol index ce9e659a0..55c696b8e 100644 --- a/l1-contracts/test/foundry/unit/concrete/Utils/UtilsFacet.sol +++ b/l1-contracts/test/foundry/unit/concrete/Utils/UtilsFacet.sol @@ -80,6 +80,14 @@ contract UtilsFacet is ZkSyncHyperchainBase { return s.l2DefaultAccountBytecodeHash; } + function util_setL2EvmSimulatorBytecodeHash(bytes32 _l2EvmSimulatorBytecodeHash) external { + s.l2EvmSimulatorBytecodeHash = _l2EvmSimulatorBytecodeHash; + } + + function util_getL2EvmSimulatorBytecodeHash() external view returns (bytes32) { + return s.l2EvmSimulatorBytecodeHash; + } + function util_setPendingAdmin(address _pendingAdmin) external { s.pendingAdmin = _pendingAdmin; } diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/DiamondInit/Initialize.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/DiamondInit/Initialize.t.sol index 3c2b01dd5..182cc5d3a 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/DiamondInit/Initialize.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/DiamondInit/Initialize.t.sol @@ -99,6 +99,7 @@ contract InitializeTest is DiamondInitTest { ); assertEq(utilsFacet.util_getL2BootloaderBytecodeHash(), initializeData.l2BootloaderBytecodeHash); assertEq(utilsFacet.util_getL2DefaultAccountBytecodeHash(), initializeData.l2DefaultAccountBytecodeHash); + assertEq(utilsFacet.util_getL2EvmSimulatorBytecodeHash();(), initializeData.l2EvmSimulatorBytecodeHash); assertEq(utilsFacet.util_getPriorityTxMaxGasLimit(), initializeData.priorityTxMaxGasLimit); assertEq( keccak256(abi.encode(utilsFacet.util_getFeeParams())), diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/_Getters_Shared.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/_Getters_Shared.t.sol index 1d64711fe..948c79925 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/_Getters_Shared.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/_Getters_Shared.t.sol @@ -90,6 +90,10 @@ contract GettersFacetWrapper is GettersFacet { s.l2DefaultAccountBytecodeHash = _l2DefaultAccountBytecodeHash; } + function utils_setL2EvmSimulatorBytecodeHash(bytes32 _l2EvmSimulatorBytecodeHash) external { + s.l2EvmSimulatorBytecodeHash = _l2EvmSimulatorBytecodeHash; + } + function util_setVerifierParams(VerifierParams memory _verifierParams) external { s.__DEPRECATED_verifierParams = _verifierParams; } diff --git a/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts b/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts index 4ea71d99d..00a8db83d 100644 --- a/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts +++ b/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts @@ -466,6 +466,7 @@ describe.only("L2 upgrade test", function () { // Now, we check that all the data was set as expected expect(await proxyGetters.getL2BootloaderBytecodeHash()).to.equal(bootloaderHash); expect(await proxyGetters.getL2DefaultAccountBytecodeHash()).to.equal(defaultAccountHash); + // TODO: SIMULATOR CODE HASH expect((await proxyGetters.getVerifier()).toLowerCase()).to.equal(newVerifier.toLowerCase()); expect(await proxyGetters.getProtocolVersion()).to.equal(addToProtocolVersion(initialProtocolVersion, 5, 0)); @@ -499,6 +500,7 @@ describe.only("L2 upgrade test", function () { expect(upgradeEvents[3].args.newBytecodeHash).to.eq(bootloaderHash); expect(upgradeEvents[4].name).to.eq("NewL2DefaultAccountBytecodeHash"); + // SIMULATOR CODE HASH expect(upgradeEvents[4].args.previousBytecodeHash).to.eq(L2_DEFAULT_ACCOUNT_BYTECODE_HASH); expect(upgradeEvents[4].args.newBytecodeHash).to.eq(defaultAccountHash); }); @@ -508,6 +510,7 @@ describe.only("L2 upgrade test", function () { const currentVerifierParams = await proxyGetters.getVerifierParams(); const currentBootloaderHash = await proxyGetters.getL2BootloaderBytecodeHash(); const currentL2DefaultAccountBytecodeHash = await proxyGetters.getL2DefaultAccountBytecodeHash(); + // SIMULATOR CODE HASH const testnetVerifierFactory = await hardhat.ethers.getContractFactory("TestnetVerifier"); const testnetVerifierContract = await testnetVerifierFactory.deploy(); @@ -552,6 +555,7 @@ describe.only("L2 upgrade test", function () { // Now, we check that all the data was set as expected expect(await proxyGetters.getL2BootloaderBytecodeHash()).to.equal(currentBootloaderHash); expect(await proxyGetters.getL2DefaultAccountBytecodeHash()).to.equal(currentL2DefaultAccountBytecodeHash); + // SIMULATOR CODE HASH expect((await proxyGetters.getVerifier()).toLowerCase()).to.equal(newVerifier.toLowerCase()); expect(await proxyGetters.getProtocolVersion()).to.equal(addToProtocolVersion(initialProtocolVersion, 5, 1)); diff --git a/l1-contracts/test/unit_tests/proxy_test.spec.ts b/l1-contracts/test/unit_tests/proxy_test.spec.ts index 3c3ae6429..24f71fb80 100644 --- a/l1-contracts/test/unit_tests/proxy_test.spec.ts +++ b/l1-contracts/test/unit_tests/proxy_test.spec.ts @@ -96,6 +96,7 @@ describe("Diamond proxy tests", function () { verifierParams: dummyVerifierParams, l2BootloaderBytecodeHash: "0x0100000000000000000000000000000000000000000000000000000000000000", l2DefaultAccountBytecodeHash: "0x0100000000000000000000000000000000000000000000000000000000000000", + // TODO: SIMULATOR CODE HASH priorityTxMaxGasLimit: 500000, // priority tx max L2 gas limit feeParams: defaultFeeParams(), blobVersionedHashRetriever: "0x0000000000000000000000000000000000000001", diff --git a/system-contracts/scripts/deploy-preimages.ts b/system-contracts/scripts/deploy-preimages.ts index 7a4a96880..7d4ca929e 100644 --- a/system-contracts/scripts/deploy-preimages.ts +++ b/system-contracts/scripts/deploy-preimages.ts @@ -23,6 +23,7 @@ const MAX_COMBINED_LENGTH = 125000; const DEFAULT_ACCOUNT_CONTRACT_NAME = "DefaultAccount"; const BOOTLOADER_CONTRACT_NAME = "Bootloader"; +const EVM_SIMULATOR_CONTRACT_NAME = "EvmInterpreter"; const CONSOLE_COLOR_RESET = "\x1b[0m"; const CONSOLE_COLOR_RED = "\x1b[31m"; @@ -157,6 +158,55 @@ class ZkSyncDeployer { return await zkSync.getL2BootloaderBytecodeHash(); } + // Returns the current default evm simulator bytecode on zkSync + async currentEvmSimulatorBytecode(): Promise { + const zkSync = await this.deployer.zkWallet.getMainContract(); + return await zkSync.getL2EvmSimulatorBytecodeHash(); + } + + // If needed, appends the evm simulator bytecode to the upgrade + async checkShouldUpgradeEvmSimulator(evmSimulatorBytecode: string) { + const bytecodeHash = ethers.utils.hexlify(hashBytecode(evmSimulatorBytecode)); + const currentEvmSimulatorBytecode = ethers.utils.hexlify(await this.currentEvmSimulatorBytecode()); + + // If the bytecode is not the same as the one deployed on zkSync, we need to add it to the deployment + if (bytecodeHash.toLowerCase() !== currentEvmSimulatorBytecode) { + this.defaultAccountToUpgrade = { + name: EVM_SIMULATOR_CONTRACT_NAME, + bytecodeHashes: [bytecodeHash], + }; + } + } + + // Publishes the bytecode of the evm simulator and appends it to the deployed bytecodes if needed. + async processEvmSimulator() { + const defaultEvmSimulator = (await this.deployer.loadArtifact(EVM_SIMULATOR_CONTRACT_NAME)).bytecode; + + await this.publishEvmSimulator(defaultEvmSimulator); + await this.checkShouldUpgradeEvmSimulator(defaultEvmSimulator); + } + + async publishEvmSimulator(defaultEvmSimulatorBytecode: string) { + const [defaultEvmSimulatorBytecodes] = await filterPublishedFactoryDeps( + EVM_SIMULATOR_CONTRACT_NAME, + [defaultEvmSimulatorBytecode], + this.deployer + ); + + if (defaultEvmSimulatorBytecodes.length == 0) { + console.log("Default evm simulator is already published, skipping"); + return; + } + + // Publish evm simulator bytecode + await this.publishFactoryDeps([ + { + name: EVM_SIMULATOR_CONTRACT_NAME, + bytecodes: defaultEvmSimulatorBytecodes, + }, + ]); + } + async checkShouldUpgradeBootloader(bootloaderCode: string) { const bytecodeHash = ethers.utils.hexlify(hashBytecode(bootloaderCode)); const currentBootloaderBytecode = ethers.utils.hexlify(await this.currentBootloaderBytecode()); @@ -302,6 +352,7 @@ async function main() { .option("--l2Rpc ") .option("--bootloader") .option("--default-aa") + .option("--evm-simulator") .option("--system-contracts") .option("--file ") .action(async (cmd) => { @@ -340,6 +391,10 @@ async function main() { await zkSyncDeployer.processDefaultAA(); } + if (cmd.evmSimulator) { + await zkSyncDeployer.processEvmSimulator(); + } + if (cmd.systemContracts) { const dependenciesToPublish = await zkSyncDeployer.prepareContractsForPublishing(); await zkSyncDeployer.publishDependencies(dependenciesToPublish); From 7487de0540f6e37b71507f03c00905f72554268e Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Mon, 12 Aug 2024 15:35:18 -0300 Subject: [PATCH 04/59] Revert solidity version update --- gas-bound-caller/contracts/GasBoundCaller.sol | 2 +- l1-contracts/deploy-scripts/InitializeL2WethToken.s.sol | 2 +- l2-contracts/contracts/SystemContractsCaller.sol | 2 +- system-contracts/contracts/AccountCodeStorage.sol | 2 +- system-contracts/contracts/BootloaderUtilities.sol | 2 +- system-contracts/contracts/ComplexUpgrader.sol | 2 +- system-contracts/contracts/Compressor.sol | 2 +- system-contracts/contracts/Constants.sol | 2 +- system-contracts/contracts/ContractDeployer.sol | 2 +- system-contracts/contracts/Create2Factory.sol | 2 +- system-contracts/contracts/DefaultAccount.sol | 2 +- system-contracts/contracts/EmptyContract.sol | 2 +- system-contracts/contracts/ImmutableSimulator.sol | 2 +- system-contracts/contracts/KnownCodesStorage.sol | 2 +- system-contracts/contracts/L1Messenger.sol | 2 +- system-contracts/contracts/L2BaseToken.sol | 2 +- system-contracts/contracts/MsgValueSimulator.sol | 2 +- system-contracts/contracts/NonceHolder.sol | 2 +- system-contracts/contracts/PubdataChunkPublisher.sol | 2 +- system-contracts/contracts/SystemContext.sol | 2 +- system-contracts/contracts/SystemContractErrors.sol | 2 +- system-contracts/contracts/interfaces/IAccount.sol | 2 +- system-contracts/contracts/interfaces/IAccountCodeStorage.sol | 2 +- system-contracts/contracts/interfaces/IBaseToken.sol | 2 +- system-contracts/contracts/interfaces/IBootloaderUtilities.sol | 2 +- system-contracts/contracts/interfaces/IComplexUpgrader.sol | 2 +- system-contracts/contracts/interfaces/ICompressor.sol | 2 +- system-contracts/contracts/interfaces/IContractDeployer.sol | 2 +- system-contracts/contracts/interfaces/IImmutableSimulator.sol | 2 +- system-contracts/contracts/interfaces/IKnownCodesStorage.sol | 2 +- system-contracts/contracts/interfaces/IL1Messenger.sol | 2 +- system-contracts/contracts/interfaces/IL2StandardToken.sol | 2 +- system-contracts/contracts/interfaces/IMailbox.sol | 2 +- system-contracts/contracts/interfaces/INonceHolder.sol | 2 +- system-contracts/contracts/interfaces/IPaymaster.sol | 2 +- system-contracts/contracts/interfaces/IPaymasterFlow.sol | 2 +- .../contracts/interfaces/IPubdataChunkPublisher.sol | 2 +- system-contracts/contracts/interfaces/ISystemContext.sol | 2 +- .../contracts/interfaces/ISystemContextDeprecated.sol | 2 +- system-contracts/contracts/interfaces/ISystemContract.sol | 2 +- system-contracts/contracts/libraries/EfficientCall.sol | 2 +- system-contracts/contracts/libraries/RLPEncoder.sol | 2 +- system-contracts/contracts/libraries/SystemContractHelper.sol | 2 +- system-contracts/contracts/libraries/SystemContractsCaller.sol | 2 +- system-contracts/contracts/libraries/TransactionHelper.sol | 2 +- system-contracts/contracts/libraries/UnsafeBytesCalldata.sol | 2 +- system-contracts/contracts/libraries/Utils.sol | 2 +- system-contracts/contracts/test-contracts/Deployable.sol | 2 +- system-contracts/contracts/test-contracts/MockContract.sol | 2 +- system-contracts/contracts/test-contracts/SystemCaller.sol | 2 +- system-contracts/hardhat.config.ts | 2 +- 51 files changed, 51 insertions(+), 51 deletions(-) diff --git a/gas-bound-caller/contracts/GasBoundCaller.sol b/gas-bound-caller/contracts/GasBoundCaller.sol index f34ecc71f..78af446ca 100644 --- a/gas-bound-caller/contracts/GasBoundCaller.sol +++ b/gas-bound-caller/contracts/GasBoundCaller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {EfficientCall} from "@matterlabs/zksync-contracts/l2/system-contracts/libraries/EfficientCall.sol"; import {ISystemContext} from "./ISystemContext.sol"; diff --git a/l1-contracts/deploy-scripts/InitializeL2WethToken.s.sol b/l1-contracts/deploy-scripts/InitializeL2WethToken.s.sol index 815008317..256980453 100644 --- a/l1-contracts/deploy-scripts/InitializeL2WethToken.s.sol +++ b/l1-contracts/deploy-scripts/InitializeL2WethToken.s.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; // solhint-disable no-console diff --git a/l2-contracts/contracts/SystemContractsCaller.sol b/l2-contracts/contracts/SystemContractsCaller.sol index aa36618bb..12cbb5475 100644 --- a/l2-contracts/contracts/SystemContractsCaller.sol +++ b/l2-contracts/contracts/SystemContractsCaller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {MSG_VALUE_SYSTEM_CONTRACT} from "./L2ContractHelper.sol"; diff --git a/system-contracts/contracts/AccountCodeStorage.sol b/system-contracts/contracts/AccountCodeStorage.sol index 30f9502ed..ff3d02b04 100644 --- a/system-contracts/contracts/AccountCodeStorage.sol +++ b/system-contracts/contracts/AccountCodeStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {IAccountCodeStorage} from "./interfaces/IAccountCodeStorage.sol"; import {Utils} from "./libraries/Utils.sol"; diff --git a/system-contracts/contracts/BootloaderUtilities.sol b/system-contracts/contracts/BootloaderUtilities.sol index 8b353c765..70232bf5a 100644 --- a/system-contracts/contracts/BootloaderUtilities.sol +++ b/system-contracts/contracts/BootloaderUtilities.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {IBootloaderUtilities} from "./interfaces/IBootloaderUtilities.sol"; import {Transaction, TransactionHelper, EIP_712_TX_TYPE, LEGACY_TX_TYPE, EIP_2930_TX_TYPE, EIP_1559_TX_TYPE} from "./libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/ComplexUpgrader.sol b/system-contracts/contracts/ComplexUpgrader.sol index 1ca1e794b..009e8994d 100644 --- a/system-contracts/contracts/ComplexUpgrader.sol +++ b/system-contracts/contracts/ComplexUpgrader.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {IComplexUpgrader} from "./interfaces/IComplexUpgrader.sol"; import {FORCE_DEPLOYER} from "./Constants.sol"; diff --git a/system-contracts/contracts/Compressor.sol b/system-contracts/contracts/Compressor.sol index 2c74e4624..73582f639 100644 --- a/system-contracts/contracts/Compressor.sol +++ b/system-contracts/contracts/Compressor.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {ICompressor, OPERATION_BITMASK, LENGTH_BITS_OFFSET, MAX_ENUMERATION_INDEX_SIZE} from "./interfaces/ICompressor.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index 7fb7b588a..792aca97b 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {IAccountCodeStorage} from "./interfaces/IAccountCodeStorage.sol"; import {INonceHolder} from "./interfaces/INonceHolder.sol"; diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 5e675260a..cef7c9081 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {ImmutableData} from "./interfaces/IImmutableSimulator.sol"; import {IContractDeployer} from "./interfaces/IContractDeployer.sol"; diff --git a/system-contracts/contracts/Create2Factory.sol b/system-contracts/contracts/Create2Factory.sol index eca05180c..6f68fbb52 100644 --- a/system-contracts/contracts/Create2Factory.sol +++ b/system-contracts/contracts/Create2Factory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {REAL_DEPLOYER_SYSTEM_CONTRACT} from "./Constants.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; diff --git a/system-contracts/contracts/DefaultAccount.sol b/system-contracts/contracts/DefaultAccount.sol index f7ca0bab7..ccd5471d9 100644 --- a/system-contracts/contracts/DefaultAccount.sol +++ b/system-contracts/contracts/DefaultAccount.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {IAccount, ACCOUNT_VALIDATION_SUCCESS_MAGIC} from "./interfaces/IAccount.sol"; import {TransactionHelper, Transaction} from "./libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/EmptyContract.sol b/system-contracts/contracts/EmptyContract.sol index 617b7e070..3f021964a 100644 --- a/system-contracts/contracts/EmptyContract.sol +++ b/system-contracts/contracts/EmptyContract.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/ImmutableSimulator.sol b/system-contracts/contracts/ImmutableSimulator.sol index 6e5034dce..701ee5d90 100644 --- a/system-contracts/contracts/ImmutableSimulator.sol +++ b/system-contracts/contracts/ImmutableSimulator.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {IImmutableSimulator, ImmutableData} from "./interfaces/IImmutableSimulator.sol"; import {DEPLOYER_SYSTEM_CONTRACT} from "./Constants.sol"; diff --git a/system-contracts/contracts/KnownCodesStorage.sol b/system-contracts/contracts/KnownCodesStorage.sol index 523bb457e..8b6e69286 100644 --- a/system-contracts/contracts/KnownCodesStorage.sol +++ b/system-contracts/contracts/KnownCodesStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {IKnownCodesStorage} from "./interfaces/IKnownCodesStorage.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/L1Messenger.sol b/system-contracts/contracts/L1Messenger.sol index b928dde6d..26d49672a 100644 --- a/system-contracts/contracts/L1Messenger.sol +++ b/system-contracts/contracts/L1Messenger.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {IL1Messenger, L2ToL1Log, L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH, L2_TO_L1_LOG_SERIALIZE_SIZE, STATE_DIFF_COMPRESSION_VERSION_NUMBER} from "./interfaces/IL1Messenger.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/L2BaseToken.sol b/system-contracts/contracts/L2BaseToken.sol index 71198c3e9..c5b934013 100644 --- a/system-contracts/contracts/L2BaseToken.sol +++ b/system-contracts/contracts/L2BaseToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {IBaseToken} from "./interfaces/IBaseToken.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/MsgValueSimulator.sol b/system-contracts/contracts/MsgValueSimulator.sol index 25e8b5200..61a221653 100644 --- a/system-contracts/contracts/MsgValueSimulator.sol +++ b/system-contracts/contracts/MsgValueSimulator.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {Utils} from "./libraries/Utils.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; diff --git a/system-contracts/contracts/NonceHolder.sol b/system-contracts/contracts/NonceHolder.sol index 4e48a42ba..2c0d71786 100644 --- a/system-contracts/contracts/NonceHolder.sol +++ b/system-contracts/contracts/NonceHolder.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {INonceHolder} from "./interfaces/INonceHolder.sol"; import {IContractDeployer} from "./interfaces/IContractDeployer.sol"; diff --git a/system-contracts/contracts/PubdataChunkPublisher.sol b/system-contracts/contracts/PubdataChunkPublisher.sol index 5dfc61042..a096e6900 100644 --- a/system-contracts/contracts/PubdataChunkPublisher.sol +++ b/system-contracts/contracts/PubdataChunkPublisher.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {IPubdataChunkPublisher} from "./interfaces/IPubdataChunkPublisher.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/SystemContext.sol b/system-contracts/contracts/SystemContext.sol index 33bd22038..d5f7d467c 100644 --- a/system-contracts/contracts/SystemContext.sol +++ b/system-contracts/contracts/SystemContext.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {ISystemContext} from "./interfaces/ISystemContext.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/SystemContractErrors.sol b/system-contracts/contracts/SystemContractErrors.sol index 3aba2a18b..5ab4ece43 100644 --- a/system-contracts/contracts/SystemContractErrors.sol +++ b/system-contracts/contracts/SystemContractErrors.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; error Unauthorized(address); error InvalidCodeHash(CodeHashReason); diff --git a/system-contracts/contracts/interfaces/IAccount.sol b/system-contracts/contracts/interfaces/IAccount.sol index dd88d68bf..c32b35767 100644 --- a/system-contracts/contracts/interfaces/IAccount.sol +++ b/system-contracts/contracts/interfaces/IAccount.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {Transaction} from "../libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/interfaces/IAccountCodeStorage.sol b/system-contracts/contracts/interfaces/IAccountCodeStorage.sol index 6e67e82f6..d616904d7 100644 --- a/system-contracts/contracts/interfaces/IAccountCodeStorage.sol +++ b/system-contracts/contracts/interfaces/IAccountCodeStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; interface IAccountCodeStorage { function storeAccountConstructingCodeHash(address _address, bytes32 _hash) external; diff --git a/system-contracts/contracts/interfaces/IBaseToken.sol b/system-contracts/contracts/interfaces/IBaseToken.sol index b1dce57f0..d15f2f123 100644 --- a/system-contracts/contracts/interfaces/IBaseToken.sol +++ b/system-contracts/contracts/interfaces/IBaseToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; interface IBaseToken { function balanceOf(uint256) external view returns (uint256); diff --git a/system-contracts/contracts/interfaces/IBootloaderUtilities.sol b/system-contracts/contracts/interfaces/IBootloaderUtilities.sol index ffbb8712d..31413320a 100644 --- a/system-contracts/contracts/interfaces/IBootloaderUtilities.sol +++ b/system-contracts/contracts/interfaces/IBootloaderUtilities.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {Transaction} from "../libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/interfaces/IComplexUpgrader.sol b/system-contracts/contracts/interfaces/IComplexUpgrader.sol index f083d9b50..1b5e15182 100644 --- a/system-contracts/contracts/interfaces/IComplexUpgrader.sol +++ b/system-contracts/contracts/interfaces/IComplexUpgrader.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ICompressor.sol b/system-contracts/contracts/interfaces/ICompressor.sol index 893e67214..3062ea4f7 100644 --- a/system-contracts/contracts/interfaces/ICompressor.sol +++ b/system-contracts/contracts/interfaces/ICompressor.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; // The bitmask by applying which to the compressed state diff metadata we retrieve its operation. uint8 constant OPERATION_BITMASK = 7; diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index 636c804e0..bc9ebc129 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; interface IContractDeployer { /// @notice Defines the version of the account abstraction protocol diff --git a/system-contracts/contracts/interfaces/IImmutableSimulator.sol b/system-contracts/contracts/interfaces/IImmutableSimulator.sol index d11422d6f..d30ac9b96 100644 --- a/system-contracts/contracts/interfaces/IImmutableSimulator.sol +++ b/system-contracts/contracts/interfaces/IImmutableSimulator.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; struct ImmutableData { uint256 index; diff --git a/system-contracts/contracts/interfaces/IKnownCodesStorage.sol b/system-contracts/contracts/interfaces/IKnownCodesStorage.sol index 1be6f1b3e..6ecc88223 100644 --- a/system-contracts/contracts/interfaces/IKnownCodesStorage.sol +++ b/system-contracts/contracts/interfaces/IKnownCodesStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/IL1Messenger.sol b/system-contracts/contracts/interfaces/IL1Messenger.sol index d8c4342da..cd0cc90f7 100644 --- a/system-contracts/contracts/interfaces/IL1Messenger.sol +++ b/system-contracts/contracts/interfaces/IL1Messenger.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; /// @dev The log passed from L2 /// @param l2ShardId The shard identifier, 0 - rollup, 1 - porter. All other values are not used but are reserved for the future diff --git a/system-contracts/contracts/interfaces/IL2StandardToken.sol b/system-contracts/contracts/interfaces/IL2StandardToken.sol index 6af08d410..3d75c8ede 100644 --- a/system-contracts/contracts/interfaces/IL2StandardToken.sol +++ b/system-contracts/contracts/interfaces/IL2StandardToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; interface IL2StandardToken { event BridgeMint(address indexed _account, uint256 _amount); diff --git a/system-contracts/contracts/interfaces/IMailbox.sol b/system-contracts/contracts/interfaces/IMailbox.sol index 1e263a2bb..ba673058c 100644 --- a/system-contracts/contracts/interfaces/IMailbox.sol +++ b/system-contracts/contracts/interfaces/IMailbox.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; interface IMailbox { function finalizeEthWithdrawal( diff --git a/system-contracts/contracts/interfaces/INonceHolder.sol b/system-contracts/contracts/interfaces/INonceHolder.sol index 2719ff8ca..1213fbea4 100644 --- a/system-contracts/contracts/interfaces/INonceHolder.sol +++ b/system-contracts/contracts/interfaces/INonceHolder.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/IPaymaster.sol b/system-contracts/contracts/interfaces/IPaymaster.sol index 6cb43249f..7b06d86ee 100644 --- a/system-contracts/contracts/interfaces/IPaymaster.sol +++ b/system-contracts/contracts/interfaces/IPaymaster.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {Transaction} from "../libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/interfaces/IPaymasterFlow.sol b/system-contracts/contracts/interfaces/IPaymasterFlow.sol index e2ceb7117..38866073e 100644 --- a/system-contracts/contracts/interfaces/IPaymasterFlow.sol +++ b/system-contracts/contracts/interfaces/IPaymasterFlow.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol b/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol index 4f781add6..83c1893fd 100644 --- a/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol +++ b/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ISystemContext.sol b/system-contracts/contracts/interfaces/ISystemContext.sol index 2ce5085f5..a122a04f5 100644 --- a/system-contracts/contracts/interfaces/ISystemContext.sol +++ b/system-contracts/contracts/interfaces/ISystemContext.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol b/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol index 954d4b5e8..a44b61b23 100644 --- a/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol +++ b/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ISystemContract.sol b/system-contracts/contracts/interfaces/ISystemContract.sol index 16bf7bb9f..1f383a823 100644 --- a/system-contracts/contracts/interfaces/ISystemContract.sol +++ b/system-contracts/contracts/interfaces/ISystemContract.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {SystemContractHelper} from "../libraries/SystemContractHelper.sol"; import {BOOTLOADER_FORMAL_ADDRESS, FORCE_DEPLOYER} from "../Constants.sol"; diff --git a/system-contracts/contracts/libraries/EfficientCall.sol b/system-contracts/contracts/libraries/EfficientCall.sol index af761ae98..70f33ae5d 100644 --- a/system-contracts/contracts/libraries/EfficientCall.sol +++ b/system-contracts/contracts/libraries/EfficientCall.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {SystemContractHelper, ADDRESS_MASK} from "./SystemContractHelper.sol"; import {SystemContractsCaller, CalldataForwardingMode, RAW_FAR_CALL_BY_REF_CALL_ADDRESS, SYSTEM_CALL_BY_REF_CALL_ADDRESS, MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT, MIMIC_CALL_BY_REF_CALL_ADDRESS} from "./SystemContractsCaller.sol"; diff --git a/system-contracts/contracts/libraries/RLPEncoder.sol b/system-contracts/contracts/libraries/RLPEncoder.sol index 70c7545a2..7bfbd2a69 100644 --- a/system-contracts/contracts/libraries/RLPEncoder.sol +++ b/system-contracts/contracts/libraries/RLPEncoder.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/libraries/SystemContractHelper.sol b/system-contracts/contracts/libraries/SystemContractHelper.sol index 226472fe6..393a3e783 100644 --- a/system-contracts/contracts/libraries/SystemContractHelper.sol +++ b/system-contracts/contracts/libraries/SystemContractHelper.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {MAX_SYSTEM_CONTRACT_ADDRESS} from "../Constants.sol"; import {Utils} from "./Utils.sol"; diff --git a/system-contracts/contracts/libraries/SystemContractsCaller.sol b/system-contracts/contracts/libraries/SystemContractsCaller.sol index dccca09af..10f92a5a5 100644 --- a/system-contracts/contracts/libraries/SystemContractsCaller.sol +++ b/system-contracts/contracts/libraries/SystemContractsCaller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {MSG_VALUE_SYSTEM_CONTRACT, MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT} from "../Constants.sol"; import {Utils} from "./Utils.sol"; diff --git a/system-contracts/contracts/libraries/TransactionHelper.sol b/system-contracts/contracts/libraries/TransactionHelper.sol index 22398fb36..b34019fc7 100644 --- a/system-contracts/contracts/libraries/TransactionHelper.sol +++ b/system-contracts/contracts/libraries/TransactionHelper.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {IERC20} from "../openzeppelin/token/ERC20/IERC20.sol"; import {SafeERC20} from "../openzeppelin/token/ERC20/utils/SafeERC20.sol"; diff --git a/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol b/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol index e61378d4c..4ce65f5fb 100644 --- a/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol +++ b/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/libraries/Utils.sol b/system-contracts/contracts/libraries/Utils.sol index b3be65224..f3d329cc0 100644 --- a/system-contracts/contracts/libraries/Utils.sol +++ b/system-contracts/contracts/libraries/Utils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {EfficientCall} from "./EfficientCall.sol"; import {RLPEncoder} from "./RLPEncoder.sol"; diff --git a/system-contracts/contracts/test-contracts/Deployable.sol b/system-contracts/contracts/test-contracts/Deployable.sol index 677b21379..be35861a4 100644 --- a/system-contracts/contracts/test-contracts/Deployable.sol +++ b/system-contracts/contracts/test-contracts/Deployable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; contract Deployable { event Deployed(uint256 value, bytes data); diff --git a/system-contracts/contracts/test-contracts/MockContract.sol b/system-contracts/contracts/test-contracts/MockContract.sol index f6419fb55..1505be34c 100644 --- a/system-contracts/contracts/test-contracts/MockContract.sol +++ b/system-contracts/contracts/test-contracts/MockContract.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; contract MockContract { event Called(uint256 value, bytes data); diff --git a/system-contracts/contracts/test-contracts/SystemCaller.sol b/system-contracts/contracts/test-contracts/SystemCaller.sol index 119afe08a..a377174ae 100644 --- a/system-contracts/contracts/test-contracts/SystemCaller.sol +++ b/system-contracts/contracts/test-contracts/SystemCaller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity 0.8.20; import {SYSTEM_CALL_CALL_ADDRESS, MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT, SystemContractsCaller, CalldataForwardingMode} from "../libraries/SystemContractsCaller.sol"; import {Utils} from "../libraries/Utils.sol"; diff --git a/system-contracts/hardhat.config.ts b/system-contracts/hardhat.config.ts index 7ad59a41f..e24721580 100644 --- a/system-contracts/hardhat.config.ts +++ b/system-contracts/hardhat.config.ts @@ -34,7 +34,7 @@ export default { ethNetwork: "http://localhost:8545", }, solidity: { - version: "0.8.24", + version: "0.8.20", settings: { evmVersion: "cancun", optimizer: { From fb58ebbeeae2a6e3e27c6c301dc9bf36e884b7e5 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Mon, 12 Aug 2024 16:14:15 -0300 Subject: [PATCH 05/59] Update solidity contracts version --- gas-bound-caller/contracts/GasBoundCaller.sol | 2 +- .../contracts/test-contracts/GasBoundCallerTester.sol | 2 +- l2-contracts/contracts/SystemContractsCaller.sol | 2 +- system-contracts/contracts/AccountCodeStorage.sol | 2 +- system-contracts/contracts/BootloaderUtilities.sol | 2 +- system-contracts/contracts/ComplexUpgrader.sol | 2 +- system-contracts/contracts/Compressor.sol | 2 +- system-contracts/contracts/Constants.sol | 2 +- system-contracts/contracts/ContractDeployer.sol | 2 +- system-contracts/contracts/Create2Factory.sol | 2 +- system-contracts/contracts/DefaultAccount.sol | 2 +- system-contracts/contracts/EmptyContract.sol | 2 +- system-contracts/contracts/ImmutableSimulator.sol | 2 +- system-contracts/contracts/KnownCodesStorage.sol | 2 +- system-contracts/contracts/L1Messenger.sol | 2 +- system-contracts/contracts/L2BaseToken.sol | 2 +- system-contracts/contracts/MsgValueSimulator.sol | 2 +- system-contracts/contracts/NonceHolder.sol | 2 +- system-contracts/contracts/PubdataChunkPublisher.sol | 2 +- system-contracts/contracts/SystemContext.sol | 2 +- system-contracts/contracts/SystemContractErrors.sol | 2 +- system-contracts/contracts/interfaces/IAccount.sol | 2 +- system-contracts/contracts/interfaces/IAccountCodeStorage.sol | 2 +- system-contracts/contracts/interfaces/IBaseToken.sol | 2 +- system-contracts/contracts/interfaces/IBootloaderUtilities.sol | 2 +- system-contracts/contracts/interfaces/IComplexUpgrader.sol | 2 +- system-contracts/contracts/interfaces/ICompressor.sol | 2 +- system-contracts/contracts/interfaces/IContractDeployer.sol | 2 +- system-contracts/contracts/interfaces/IImmutableSimulator.sol | 2 +- system-contracts/contracts/interfaces/IKnownCodesStorage.sol | 2 +- system-contracts/contracts/interfaces/IL1Messenger.sol | 2 +- system-contracts/contracts/interfaces/IL2StandardToken.sol | 2 +- system-contracts/contracts/interfaces/IMailbox.sol | 2 +- system-contracts/contracts/interfaces/INonceHolder.sol | 2 +- system-contracts/contracts/interfaces/IPaymaster.sol | 2 +- system-contracts/contracts/interfaces/IPaymasterFlow.sol | 2 +- .../contracts/interfaces/IPubdataChunkPublisher.sol | 2 +- system-contracts/contracts/interfaces/ISystemContext.sol | 2 +- .../contracts/interfaces/ISystemContextDeprecated.sol | 2 +- system-contracts/contracts/interfaces/ISystemContract.sol | 2 +- system-contracts/contracts/libraries/EfficientCall.sol | 2 +- system-contracts/contracts/libraries/RLPEncoder.sol | 2 +- system-contracts/contracts/libraries/SystemContractHelper.sol | 2 +- system-contracts/contracts/libraries/SystemContractsCaller.sol | 2 +- system-contracts/contracts/libraries/TransactionHelper.sol | 2 +- system-contracts/contracts/libraries/UnsafeBytesCalldata.sol | 2 +- system-contracts/contracts/libraries/Utils.sol | 2 +- system-contracts/contracts/test-contracts/Deployable.sol | 2 +- system-contracts/contracts/test-contracts/MockContract.sol | 2 +- system-contracts/contracts/test-contracts/SystemCaller.sol | 2 +- system-contracts/hardhat.config.ts | 3 ++- 51 files changed, 52 insertions(+), 51 deletions(-) diff --git a/gas-bound-caller/contracts/GasBoundCaller.sol b/gas-bound-caller/contracts/GasBoundCaller.sol index 78af446ca..f34ecc71f 100644 --- a/gas-bound-caller/contracts/GasBoundCaller.sol +++ b/gas-bound-caller/contracts/GasBoundCaller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {EfficientCall} from "@matterlabs/zksync-contracts/l2/system-contracts/libraries/EfficientCall.sol"; import {ISystemContext} from "./ISystemContext.sol"; diff --git a/gas-bound-caller/contracts/test-contracts/GasBoundCallerTester.sol b/gas-bound-caller/contracts/test-contracts/GasBoundCallerTester.sol index 1314bf0c0..c3430fd9b 100644 --- a/gas-bound-caller/contracts/test-contracts/GasBoundCallerTester.sol +++ b/gas-bound-caller/contracts/test-contracts/GasBoundCallerTester.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {GasBoundCaller} from "../GasBoundCaller.sol"; import {SystemContractHelper} from "./SystemContractHelper.sol"; diff --git a/l2-contracts/contracts/SystemContractsCaller.sol b/l2-contracts/contracts/SystemContractsCaller.sol index 97753cbac..b7880f168 100644 --- a/l2-contracts/contracts/SystemContractsCaller.sol +++ b/l2-contracts/contracts/SystemContractsCaller.sol @@ -2,7 +2,7 @@ // solhint-disable one-contract-per-file -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {MSG_VALUE_SYSTEM_CONTRACT} from "./L2ContractHelper.sol"; diff --git a/system-contracts/contracts/AccountCodeStorage.sol b/system-contracts/contracts/AccountCodeStorage.sol index 5df2fdd8b..c40ae10be 100644 --- a/system-contracts/contracts/AccountCodeStorage.sol +++ b/system-contracts/contracts/AccountCodeStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IAccountCodeStorage} from "./interfaces/IAccountCodeStorage.sol"; import {Utils} from "./libraries/Utils.sol"; diff --git a/system-contracts/contracts/BootloaderUtilities.sol b/system-contracts/contracts/BootloaderUtilities.sol index 0aafee7be..eee31bd0f 100644 --- a/system-contracts/contracts/BootloaderUtilities.sol +++ b/system-contracts/contracts/BootloaderUtilities.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IBootloaderUtilities} from "./interfaces/IBootloaderUtilities.sol"; import {Transaction, TransactionHelper, EIP_712_TX_TYPE, LEGACY_TX_TYPE, EIP_2930_TX_TYPE, EIP_1559_TX_TYPE} from "./libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/ComplexUpgrader.sol b/system-contracts/contracts/ComplexUpgrader.sol index 009e8994d..1ca1e794b 100644 --- a/system-contracts/contracts/ComplexUpgrader.sol +++ b/system-contracts/contracts/ComplexUpgrader.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IComplexUpgrader} from "./interfaces/IComplexUpgrader.sol"; import {FORCE_DEPLOYER} from "./Constants.sol"; diff --git a/system-contracts/contracts/Compressor.sol b/system-contracts/contracts/Compressor.sol index 73582f639..2c74e4624 100644 --- a/system-contracts/contracts/Compressor.sol +++ b/system-contracts/contracts/Compressor.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {ICompressor, OPERATION_BITMASK, LENGTH_BITS_OFFSET, MAX_ENUMERATION_INDEX_SIZE} from "./interfaces/ICompressor.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index fde7a5de5..a5c916a7b 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IAccountCodeStorage} from "./interfaces/IAccountCodeStorage.sol"; import {INonceHolder} from "./interfaces/INonceHolder.sol"; diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 3148de8ff..b56cab0fd 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {ImmutableData} from "./interfaces/IImmutableSimulator.sol"; import {IContractDeployer} from "./interfaces/IContractDeployer.sol"; diff --git a/system-contracts/contracts/Create2Factory.sol b/system-contracts/contracts/Create2Factory.sol index 6f68fbb52..eca05180c 100644 --- a/system-contracts/contracts/Create2Factory.sol +++ b/system-contracts/contracts/Create2Factory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {REAL_DEPLOYER_SYSTEM_CONTRACT} from "./Constants.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; diff --git a/system-contracts/contracts/DefaultAccount.sol b/system-contracts/contracts/DefaultAccount.sol index ff62e9a57..51a88d6e6 100644 --- a/system-contracts/contracts/DefaultAccount.sol +++ b/system-contracts/contracts/DefaultAccount.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IAccount, ACCOUNT_VALIDATION_SUCCESS_MAGIC} from "./interfaces/IAccount.sol"; import {TransactionHelper, Transaction} from "./libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/EmptyContract.sol b/system-contracts/contracts/EmptyContract.sol index 3f021964a..617b7e070 100644 --- a/system-contracts/contracts/EmptyContract.sol +++ b/system-contracts/contracts/EmptyContract.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/ImmutableSimulator.sol b/system-contracts/contracts/ImmutableSimulator.sol index 701ee5d90..6e5034dce 100644 --- a/system-contracts/contracts/ImmutableSimulator.sol +++ b/system-contracts/contracts/ImmutableSimulator.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IImmutableSimulator, ImmutableData} from "./interfaces/IImmutableSimulator.sol"; import {DEPLOYER_SYSTEM_CONTRACT} from "./Constants.sol"; diff --git a/system-contracts/contracts/KnownCodesStorage.sol b/system-contracts/contracts/KnownCodesStorage.sol index efddf5d9c..9d3b3a325 100644 --- a/system-contracts/contracts/KnownCodesStorage.sol +++ b/system-contracts/contracts/KnownCodesStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IKnownCodesStorage} from "./interfaces/IKnownCodesStorage.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/L1Messenger.sol b/system-contracts/contracts/L1Messenger.sol index 26d49672a..b928dde6d 100644 --- a/system-contracts/contracts/L1Messenger.sol +++ b/system-contracts/contracts/L1Messenger.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IL1Messenger, L2ToL1Log, L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH, L2_TO_L1_LOG_SERIALIZE_SIZE, STATE_DIFF_COMPRESSION_VERSION_NUMBER} from "./interfaces/IL1Messenger.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/L2BaseToken.sol b/system-contracts/contracts/L2BaseToken.sol index c5b934013..71198c3e9 100644 --- a/system-contracts/contracts/L2BaseToken.sol +++ b/system-contracts/contracts/L2BaseToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IBaseToken} from "./interfaces/IBaseToken.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/MsgValueSimulator.sol b/system-contracts/contracts/MsgValueSimulator.sol index 61a221653..25e8b5200 100644 --- a/system-contracts/contracts/MsgValueSimulator.sol +++ b/system-contracts/contracts/MsgValueSimulator.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {Utils} from "./libraries/Utils.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; diff --git a/system-contracts/contracts/NonceHolder.sol b/system-contracts/contracts/NonceHolder.sol index b769d2d37..13b6d8529 100644 --- a/system-contracts/contracts/NonceHolder.sol +++ b/system-contracts/contracts/NonceHolder.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {INonceHolder} from "./interfaces/INonceHolder.sol"; import {IContractDeployer} from "./interfaces/IContractDeployer.sol"; diff --git a/system-contracts/contracts/PubdataChunkPublisher.sol b/system-contracts/contracts/PubdataChunkPublisher.sol index a096e6900..5dfc61042 100644 --- a/system-contracts/contracts/PubdataChunkPublisher.sol +++ b/system-contracts/contracts/PubdataChunkPublisher.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IPubdataChunkPublisher} from "./interfaces/IPubdataChunkPublisher.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/SystemContext.sol b/system-contracts/contracts/SystemContext.sol index a37cf0c19..d54942eb0 100644 --- a/system-contracts/contracts/SystemContext.sol +++ b/system-contracts/contracts/SystemContext.sol @@ -2,7 +2,7 @@ // solhint-disable reason-string, gas-custom-errors -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {ISystemContext} from "./interfaces/ISystemContext.sol"; import {ISystemContract} from "./interfaces/ISystemContract.sol"; diff --git a/system-contracts/contracts/SystemContractErrors.sol b/system-contracts/contracts/SystemContractErrors.sol index 5ab4ece43..3aba2a18b 100644 --- a/system-contracts/contracts/SystemContractErrors.sol +++ b/system-contracts/contracts/SystemContractErrors.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; error Unauthorized(address); error InvalidCodeHash(CodeHashReason); diff --git a/system-contracts/contracts/interfaces/IAccount.sol b/system-contracts/contracts/interfaces/IAccount.sol index c32b35767..dd88d68bf 100644 --- a/system-contracts/contracts/interfaces/IAccount.sol +++ b/system-contracts/contracts/interfaces/IAccount.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {Transaction} from "../libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/interfaces/IAccountCodeStorage.sol b/system-contracts/contracts/interfaces/IAccountCodeStorage.sol index c266774ea..014c9439c 100644 --- a/system-contracts/contracts/interfaces/IAccountCodeStorage.sol +++ b/system-contracts/contracts/interfaces/IAccountCodeStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; interface IAccountCodeStorage { function storeAccountConstructingCodeHash(address _address, bytes32 _hash) external; diff --git a/system-contracts/contracts/interfaces/IBaseToken.sol b/system-contracts/contracts/interfaces/IBaseToken.sol index d15f2f123..b1dce57f0 100644 --- a/system-contracts/contracts/interfaces/IBaseToken.sol +++ b/system-contracts/contracts/interfaces/IBaseToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; interface IBaseToken { function balanceOf(uint256) external view returns (uint256); diff --git a/system-contracts/contracts/interfaces/IBootloaderUtilities.sol b/system-contracts/contracts/interfaces/IBootloaderUtilities.sol index 31413320a..ffbb8712d 100644 --- a/system-contracts/contracts/interfaces/IBootloaderUtilities.sol +++ b/system-contracts/contracts/interfaces/IBootloaderUtilities.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {Transaction} from "../libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/interfaces/IComplexUpgrader.sol b/system-contracts/contracts/interfaces/IComplexUpgrader.sol index 1b5e15182..f083d9b50 100644 --- a/system-contracts/contracts/interfaces/IComplexUpgrader.sol +++ b/system-contracts/contracts/interfaces/IComplexUpgrader.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ICompressor.sol b/system-contracts/contracts/interfaces/ICompressor.sol index 3062ea4f7..893e67214 100644 --- a/system-contracts/contracts/interfaces/ICompressor.sol +++ b/system-contracts/contracts/interfaces/ICompressor.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; // The bitmask by applying which to the compressed state diff metadata we retrieve its operation. uint8 constant OPERATION_BITMASK = 7; diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index 3f84672d7..5da7b49a3 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; interface IContractDeployer { /// @notice Defines the version of the account abstraction protocol diff --git a/system-contracts/contracts/interfaces/IImmutableSimulator.sol b/system-contracts/contracts/interfaces/IImmutableSimulator.sol index d30ac9b96..d11422d6f 100644 --- a/system-contracts/contracts/interfaces/IImmutableSimulator.sol +++ b/system-contracts/contracts/interfaces/IImmutableSimulator.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; struct ImmutableData { uint256 index; diff --git a/system-contracts/contracts/interfaces/IKnownCodesStorage.sol b/system-contracts/contracts/interfaces/IKnownCodesStorage.sol index 98a1277d0..58887e099 100644 --- a/system-contracts/contracts/interfaces/IKnownCodesStorage.sol +++ b/system-contracts/contracts/interfaces/IKnownCodesStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/IL1Messenger.sol b/system-contracts/contracts/interfaces/IL1Messenger.sol index cd0cc90f7..d8c4342da 100644 --- a/system-contracts/contracts/interfaces/IL1Messenger.sol +++ b/system-contracts/contracts/interfaces/IL1Messenger.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /// @dev The log passed from L2 /// @param l2ShardId The shard identifier, 0 - rollup, 1 - porter. All other values are not used but are reserved for the future diff --git a/system-contracts/contracts/interfaces/IL2StandardToken.sol b/system-contracts/contracts/interfaces/IL2StandardToken.sol index 3d75c8ede..6af08d410 100644 --- a/system-contracts/contracts/interfaces/IL2StandardToken.sol +++ b/system-contracts/contracts/interfaces/IL2StandardToken.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; interface IL2StandardToken { event BridgeMint(address indexed _account, uint256 _amount); diff --git a/system-contracts/contracts/interfaces/IMailbox.sol b/system-contracts/contracts/interfaces/IMailbox.sol index ba673058c..1e263a2bb 100644 --- a/system-contracts/contracts/interfaces/IMailbox.sol +++ b/system-contracts/contracts/interfaces/IMailbox.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; interface IMailbox { function finalizeEthWithdrawal( diff --git a/system-contracts/contracts/interfaces/INonceHolder.sol b/system-contracts/contracts/interfaces/INonceHolder.sol index 1213fbea4..2719ff8ca 100644 --- a/system-contracts/contracts/interfaces/INonceHolder.sol +++ b/system-contracts/contracts/interfaces/INonceHolder.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/IPaymaster.sol b/system-contracts/contracts/interfaces/IPaymaster.sol index 7b06d86ee..6cb43249f 100644 --- a/system-contracts/contracts/interfaces/IPaymaster.sol +++ b/system-contracts/contracts/interfaces/IPaymaster.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {Transaction} from "../libraries/TransactionHelper.sol"; diff --git a/system-contracts/contracts/interfaces/IPaymasterFlow.sol b/system-contracts/contracts/interfaces/IPaymasterFlow.sol index 38866073e..e2ceb7117 100644 --- a/system-contracts/contracts/interfaces/IPaymasterFlow.sol +++ b/system-contracts/contracts/interfaces/IPaymasterFlow.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol b/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol index 83c1893fd..4f781add6 100644 --- a/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol +++ b/system-contracts/contracts/interfaces/IPubdataChunkPublisher.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ISystemContext.sol b/system-contracts/contracts/interfaces/ISystemContext.sol index a122a04f5..2ce5085f5 100644 --- a/system-contracts/contracts/interfaces/ISystemContext.sol +++ b/system-contracts/contracts/interfaces/ISystemContext.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol b/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol index a44b61b23..954d4b5e8 100644 --- a/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol +++ b/system-contracts/contracts/interfaces/ISystemContextDeprecated.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/interfaces/ISystemContract.sol b/system-contracts/contracts/interfaces/ISystemContract.sol index 1f383a823..16bf7bb9f 100644 --- a/system-contracts/contracts/interfaces/ISystemContract.sol +++ b/system-contracts/contracts/interfaces/ISystemContract.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {SystemContractHelper} from "../libraries/SystemContractHelper.sol"; import {BOOTLOADER_FORMAL_ADDRESS, FORCE_DEPLOYER} from "../Constants.sol"; diff --git a/system-contracts/contracts/libraries/EfficientCall.sol b/system-contracts/contracts/libraries/EfficientCall.sol index 70f33ae5d..af761ae98 100644 --- a/system-contracts/contracts/libraries/EfficientCall.sol +++ b/system-contracts/contracts/libraries/EfficientCall.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {SystemContractHelper, ADDRESS_MASK} from "./SystemContractHelper.sol"; import {SystemContractsCaller, CalldataForwardingMode, RAW_FAR_CALL_BY_REF_CALL_ADDRESS, SYSTEM_CALL_BY_REF_CALL_ADDRESS, MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT, MIMIC_CALL_BY_REF_CALL_ADDRESS} from "./SystemContractsCaller.sol"; diff --git a/system-contracts/contracts/libraries/RLPEncoder.sol b/system-contracts/contracts/libraries/RLPEncoder.sol index 7bfbd2a69..70c7545a2 100644 --- a/system-contracts/contracts/libraries/RLPEncoder.sol +++ b/system-contracts/contracts/libraries/RLPEncoder.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/libraries/SystemContractHelper.sol b/system-contracts/contracts/libraries/SystemContractHelper.sol index 14d29f100..3cda395c1 100644 --- a/system-contracts/contracts/libraries/SystemContractHelper.sol +++ b/system-contracts/contracts/libraries/SystemContractHelper.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {MAX_SYSTEM_CONTRACT_ADDRESS} from "../Constants.sol"; diff --git a/system-contracts/contracts/libraries/SystemContractsCaller.sol b/system-contracts/contracts/libraries/SystemContractsCaller.sol index d964fbbe7..7edb54145 100644 --- a/system-contracts/contracts/libraries/SystemContractsCaller.sol +++ b/system-contracts/contracts/libraries/SystemContractsCaller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {MSG_VALUE_SYSTEM_CONTRACT, MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT} from "../Constants.sol"; import {Utils} from "./Utils.sol"; diff --git a/system-contracts/contracts/libraries/TransactionHelper.sol b/system-contracts/contracts/libraries/TransactionHelper.sol index fbdc57919..632e9ff46 100644 --- a/system-contracts/contracts/libraries/TransactionHelper.sol +++ b/system-contracts/contracts/libraries/TransactionHelper.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {IERC20} from "../openzeppelin/token/ERC20/IERC20.sol"; import {SafeERC20} from "../openzeppelin/token/ERC20/utils/SafeERC20.sol"; diff --git a/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol b/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol index 4ce65f5fb..e61378d4c 100644 --- a/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol +++ b/system-contracts/contracts/libraries/UnsafeBytesCalldata.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; /** * @author Matter Labs diff --git a/system-contracts/contracts/libraries/Utils.sol b/system-contracts/contracts/libraries/Utils.sol index 4f535e2c1..7532c71af 100644 --- a/system-contracts/contracts/libraries/Utils.sol +++ b/system-contracts/contracts/libraries/Utils.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {EfficientCall} from "./EfficientCall.sol"; import {MalformedBytecode, BytecodeError, Overflow} from "../SystemContractErrors.sol"; diff --git a/system-contracts/contracts/test-contracts/Deployable.sol b/system-contracts/contracts/test-contracts/Deployable.sol index be35861a4..677b21379 100644 --- a/system-contracts/contracts/test-contracts/Deployable.sol +++ b/system-contracts/contracts/test-contracts/Deployable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; contract Deployable { event Deployed(uint256 value, bytes data); diff --git a/system-contracts/contracts/test-contracts/MockContract.sol b/system-contracts/contracts/test-contracts/MockContract.sol index 1505be34c..f6419fb55 100644 --- a/system-contracts/contracts/test-contracts/MockContract.sol +++ b/system-contracts/contracts/test-contracts/MockContract.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; contract MockContract { event Called(uint256 value, bytes data); diff --git a/system-contracts/contracts/test-contracts/SystemCaller.sol b/system-contracts/contracts/test-contracts/SystemCaller.sol index a377174ae..119afe08a 100644 --- a/system-contracts/contracts/test-contracts/SystemCaller.sol +++ b/system-contracts/contracts/test-contracts/SystemCaller.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import {SYSTEM_CALL_CALL_ADDRESS, MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT, SystemContractsCaller, CalldataForwardingMode} from "../libraries/SystemContractsCaller.sol"; import {Utils} from "../libraries/Utils.sol"; diff --git a/system-contracts/hardhat.config.ts b/system-contracts/hardhat.config.ts index 68550e6c3..7ad59a41f 100644 --- a/system-contracts/hardhat.config.ts +++ b/system-contracts/hardhat.config.ts @@ -34,8 +34,9 @@ export default { ethNetwork: "http://localhost:8545", }, solidity: { - version: "0.8.20", + version: "0.8.24", settings: { + evmVersion: "cancun", optimizer: { enabled: true, runs: 9999999, From 90e7043091b4a00a5a2b1afe2da0877aa61e258b Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Mon, 12 Aug 2024 17:46:46 -0300 Subject: [PATCH 06/59] Calculate evm simulator address from compiled file when deploying --- l1-contracts/scripts/utils.ts | 7 +++++++ l1-contracts/src.ts/deploy-process.ts | 3 +-- l1-contracts/src.ts/deploy.ts | 7 ++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/l1-contracts/scripts/utils.ts b/l1-contracts/scripts/utils.ts index 5ae1bceac..a012674b5 100644 --- a/l1-contracts/scripts/utils.ts +++ b/l1-contracts/scripts/utils.ts @@ -70,6 +70,13 @@ export function readSystemContractsBytecode(fileName: string) { return JSON.parse(artifact.toString()).bytecode; } +export function readEvmSimulatorbytecode() { + const systemContractsPath = path.join(process.env.ZKSYNC_HOME as string, "contracts/system-contracts"); + return fs.readFileSync( + `${systemContractsPath}/contracts-preprocessed/artifacts/EvmInterpreter.yul.zbin` + ); +} + // eslint-disable-next-line @typescript-eslint/no-explicit-any export function print(name: string, data: any) { console.log(`${name}:\n`, JSON.stringify(data, null, 4), "\n"); diff --git a/l1-contracts/src.ts/deploy-process.ts b/l1-contracts/src.ts/deploy-process.ts index 596e4136c..884fe664e 100644 --- a/l1-contracts/src.ts/deploy-process.ts +++ b/l1-contracts/src.ts/deploy-process.ts @@ -16,8 +16,7 @@ import { ADDRESS_ONE } from "../src.ts/utils"; export const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000"; export const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; -// This is the actual hash, not a placeholder like the other two. -export const L2_EVM_SIMULATOR_BYTECODE_HASH = "0x01000f197081a9906cc411d0698c4961aeb5c74877f37f7071681da6e8ef3f31"; +export const L2_EVM_SIMULATOR_BYTECODE_HASH = "0x1010000000000000000000000000000000000000000000000000000000000000"; export async function initialBridgehubDeployment( deployer: Deployer, diff --git a/l1-contracts/src.ts/deploy.ts b/l1-contracts/src.ts/deploy.ts index 24ac43074..45251932b 100644 --- a/l1-contracts/src.ts/deploy.ts +++ b/l1-contracts/src.ts/deploy.ts @@ -10,6 +10,7 @@ import { packSemver, readBatchBootloaderBytecode, readSystemContractsBytecode, + readEvmSimulatorbytecode, unpackStringSemVer, } from "../scripts/utils"; import { getTokens } from "./deploy-token"; @@ -40,10 +41,10 @@ import { getCurrentFacetCutsForAdd } from "./diamondCut"; import { ChainAdminFactory, ERC20Factory, StateTransitionManagerFactory } from "../typechain"; import type { Contract, Overrides } from "@ethersproject/contracts"; -import { L2_EVM_SIMULATOR_BYTECODE_HASH } from "./deploy-process"; let L2_BOOTLOADER_BYTECODE_HASH: string; let L2_DEFAULT_ACCOUNT_BYTECODE_HASH: string; +let L2_EVM_SIMULATOR_BYTECODE_HASH: string; export interface DeployerConfig { deployWallet: Wallet; @@ -52,6 +53,7 @@ export interface DeployerConfig { verbose?: boolean; bootloaderBytecodeHash?: string; defaultAccountBytecodeHash?: string; + evmSimulatorBytecodeHash?: string; } export interface Operation { @@ -79,6 +81,9 @@ export class Deployer { L2_DEFAULT_ACCOUNT_BYTECODE_HASH = config.defaultAccountBytecodeHash ? config.defaultAccountBytecodeHash : hexlify(hashL2Bytecode(readSystemContractsBytecode("DefaultAccount"))); + L2_EVM_SIMULATOR_BYTECODE_HASH = config.evmSimulatorBytecodeHash + ? config.evmSimulatorBytecodeHash + : hexlify(hashL2Bytecode(readEvmSimulatorbytecode())); this.ownerAddress = config.ownerAddress != null ? config.ownerAddress : this.deployWallet.address; this.chainId = parseInt(process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!); } From 6b78beb8a268974362511fa1932b998cbe7b6a4d Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 14 Aug 2024 18:00:30 -0300 Subject: [PATCH 07/59] Comment out assert in bootloader to deploy evm contracts --- system-contracts/bootloader/bootloader.yul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system-contracts/bootloader/bootloader.yul b/system-contracts/bootloader/bootloader.yul index 85cc33dda..b31246a9a 100644 --- a/system-contracts/bootloader/bootloader.yul +++ b/system-contracts/bootloader/bootloader.yul @@ -3180,7 +3180,7 @@ object "Bootloader" { assertEq(gt(getFrom(innerTxDataOffset), MAX_SYSTEM_CONTRACT_ADDR()), 1, "from in kernel space") - assertEq(getReserved1(innerTxDataOffset), 0, "reserved1 non zero") + // assertEq(getReserved1(innerTxDataOffset), 0, "reserved1 non zero") assertEq(getReserved2(innerTxDataOffset), 0, "reserved2 non zero") assertEq(getReserved3(innerTxDataOffset), 0, "reserved3 non zero") assertEq(getFactoryDepsBytesLength(innerTxDataOffset), 0, "factory deps non zero") From 7cce99c2015eed4b1c8982b77d3648ae82d79a39 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 15 Aug 2024 02:09:03 -0300 Subject: [PATCH 08/59] Remove solhint line added by mistake --- l2-contracts/contracts/SystemContractsCaller.sol | 2 -- system-contracts/contracts/SystemContext.sol | 2 -- 2 files changed, 4 deletions(-) diff --git a/l2-contracts/contracts/SystemContractsCaller.sol b/l2-contracts/contracts/SystemContractsCaller.sol index b7880f168..aa36618bb 100644 --- a/l2-contracts/contracts/SystemContractsCaller.sol +++ b/l2-contracts/contracts/SystemContractsCaller.sol @@ -1,7 +1,5 @@ // SPDX-License-Identifier: MIT -// solhint-disable one-contract-per-file - pragma solidity ^0.8.20; import {MSG_VALUE_SYSTEM_CONTRACT} from "./L2ContractHelper.sol"; diff --git a/system-contracts/contracts/SystemContext.sol b/system-contracts/contracts/SystemContext.sol index d54942eb0..33bd22038 100644 --- a/system-contracts/contracts/SystemContext.sol +++ b/system-contracts/contracts/SystemContext.sol @@ -1,7 +1,5 @@ // SPDX-License-Identifier: MIT -// solhint-disable reason-string, gas-custom-errors - pragma solidity ^0.8.20; import {ISystemContext} from "./interfaces/ISystemContext.sol"; From 8eeffbad0a03e0f51f99d82be7e3e7cb08c36132 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Fri, 16 Aug 2024 19:22:08 -0300 Subject: [PATCH 09/59] Update contracts to emit events on evm deployment --- system-contracts/contracts/ContractDeployer.sol | 1 + system-contracts/contracts/KnownCodesStorage.sol | 2 ++ 2 files changed, 3 insertions(+) diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index cef7c9081..39b16d4bb 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -534,5 +534,6 @@ contract ContractDeployer is IContractDeployer, ISystemContract { } require(evmCodeHash[_newAddress] != 0x0, "The code hash must be set after the constructor call"); + emit ContractDeployed(_sender, evmCodeHash[_newAddress], _newAddress); } } diff --git a/system-contracts/contracts/KnownCodesStorage.sol b/system-contracts/contracts/KnownCodesStorage.sol index 8b6e69286..f105ed642 100644 --- a/system-contracts/contracts/KnownCodesStorage.sol +++ b/system-contracts/contracts/KnownCodesStorage.sol @@ -101,5 +101,7 @@ contract KnownCodesStorage is IKnownCodesStorage, ISystemContract { sstore(hash, 1) } } + + emit MarkedAsKnown(hash, getMarker(hash) == 0); } } From be4715462c680167077464b04498319f623cd55a Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Mon, 19 Aug 2024 18:58:12 -0300 Subject: [PATCH 10/59] Fix typos --- .../contracts/ContractDeployer.sol | 2 +- system-contracts/contracts/DefaultAccount.sol | 2 +- system-contracts/contracts/EvmGasManager.sol | 4 ++-- system-contracts/contracts/EvmInterpreter.yul | 24 +++++++++---------- .../contracts/precompiles/CodeOracle.yul | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 39b16d4bb..95dc6b42b 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -386,7 +386,7 @@ contract ContractDeployer is IContractDeployer, ISystemContract { } function convertToConstructorEVMInput(bytes calldata _input) internal pure returns (bytes memory) { - // With how the contracts work, the calldata to the constuctor must be an ABI-encoded `bytes`. + // With how the contracts work, the calldata to the constructor must be an ABI-encoded `bytes`. // This means that it should also contain offset as well as length uint256 _fullLength = _input.length; bytes memory extendedInput = new bytes(_input.length + 64); diff --git a/system-contracts/contracts/DefaultAccount.sol b/system-contracts/contracts/DefaultAccount.sol index ccd5471d9..890b8b888 100644 --- a/system-contracts/contracts/DefaultAccount.sol +++ b/system-contracts/contracts/DefaultAccount.sol @@ -139,7 +139,7 @@ contract DefaultAccount is IAccount { bytes calldata data = _transaction.data; uint32 gas = Utils.safeCastToU32(gasleft()); - // TODO: if possible, maybe implment some way to avoid memory copying here. + // TODO: if possible, maybe implement some way to avoid memory copying here. if (_transaction.reserved[1] != 0) { DEPLOYER_SYSTEM_CONTRACT.createEVM{value: value}(data); return; diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index 64fb86293..e9ae9ae47 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -12,7 +12,7 @@ uint160 constant PRECOMPILES_END = 0xffff; uint256 constant INF_PASS_GAS = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; contract EvmGasManager { - // We need strust to use `storage` pointers + // We need trust to use `storage` pointers struct WarmAccountInfo { bool isWarm; } @@ -115,7 +115,7 @@ contract EvmGasManager { The flow is the following: When conducting call: 1. caller calls to an EVM contract pushEVMFrame with the corresponding gas - 2. callee calls consumeEvmFrame to get the gas & make sure that subsequent callee wont be able to read it. + 2. callee calls consumeEvmFrame to get the gas & make sure that subsequent callee won't be able to read it. 3. callee sets the return gas 4. callee calls popEVMFrame to return the gas to the caller & remove the frame */ diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmInterpreter.yul index 2780a9625..faa6aff7e 100644 --- a/system-contracts/contracts/EvmInterpreter.yul +++ b/system-contracts/contracts/EvmInterpreter.yul @@ -444,7 +444,7 @@ object "EVMInterpreter" { // The gas cost mentioned here is purely the cost of the contract, // and does not consider the cost of the call itself nor the instructions // to put the parameters in memory. - // Take into account MEM_OFFSET_INNER() when passing the argsOfsset + // Take into account MEM_OFFSET_INNER() when passing the argsOffset function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { switch addr case 0x01 { // ecRecover @@ -763,7 +763,7 @@ object "EVMInterpreter" { function ensureAcceptableMemLocation(location) { if gt(location,MAX_POSSIBLE_MEM()) { - revert(0,0) // Check if this is whats needed + revert(0,0) // Check if this is what's needed } } @@ -1014,7 +1014,7 @@ object "EVMInterpreter" { if _isEVM(addr) { _pushEVMFrame(gasToPass, true) // TODO Check the following comment from zkSync .sol. - // We can not just pass all gas here to prevert overflow of zkEVM gas counter + // We can not just pass all gas here to prevent overflow of zkEVM gas counter success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) @@ -1211,7 +1211,7 @@ object "EVMInterpreter" { _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( - // We can not just pass all gas here to prevert overflow of zkEVM gas counter + // We can not just pass all gas here to prevent overflow of zkEVM gas counter EVM_GAS_STIPEND(), addr, add(MEM_OFFSET_INNER(), argsOffset), @@ -1273,7 +1273,7 @@ object "EVMInterpreter" { if _calleeIsEVM { _pushEVMFrame(_calleeGas, true) // TODO Check the following comment from zkSync .sol. - // We can not just pass all gas here to prevert overflow of zkEVM gas counter + // We can not just pass all gas here to prevent overflow of zkEVM gas counter success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) @@ -2036,7 +2036,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - // TODO: check, the .sol uses extcodesize directly, but it doesnt seem to work + // TODO: check, the .sol uses extcodesize directly, but it doesn't seem to work // if a contract is created it works, but if the address is a zkSync's contract // what happens? // sp := pushStackItem(sp, extcodesize(addr), evmGasLeft) @@ -3439,7 +3439,7 @@ object "EVMInterpreter" { // The gas cost mentioned here is purely the cost of the contract, // and does not consider the cost of the call itself nor the instructions // to put the parameters in memory. - // Take into account MEM_OFFSET_INNER() when passing the argsOfsset + // Take into account MEM_OFFSET_INNER() when passing the argsOffset function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { switch addr case 0x01 { // ecRecover @@ -3758,7 +3758,7 @@ object "EVMInterpreter" { function ensureAcceptableMemLocation(location) { if gt(location,MAX_POSSIBLE_MEM()) { - revert(0,0) // Check if this is whats needed + revert(0,0) // Check if this is what's needed } } @@ -4009,7 +4009,7 @@ object "EVMInterpreter" { if _isEVM(addr) { _pushEVMFrame(gasToPass, true) // TODO Check the following comment from zkSync .sol. - // We can not just pass all gas here to prevert overflow of zkEVM gas counter + // We can not just pass all gas here to prevent overflow of zkEVM gas counter success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) @@ -4206,7 +4206,7 @@ object "EVMInterpreter" { _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( - // We can not just pass all gas here to prevert overflow of zkEVM gas counter + // We can not just pass all gas here to prevent overflow of zkEVM gas counter EVM_GAS_STIPEND(), addr, add(MEM_OFFSET_INNER(), argsOffset), @@ -4268,7 +4268,7 @@ object "EVMInterpreter" { if _calleeIsEVM { _pushEVMFrame(_calleeGas, true) // TODO Check the following comment from zkSync .sol. - // We can not just pass all gas here to prevert overflow of zkEVM gas counter + // We can not just pass all gas here to prevent overflow of zkEVM gas counter success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) @@ -5031,7 +5031,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - // TODO: check, the .sol uses extcodesize directly, but it doesnt seem to work + // TODO: check, the .sol uses extcodesize directly, but it doesn't seem to work // if a contract is created it works, but if the address is a zkSync's contract // what happens? // sp := pushStackItem(sp, extcodesize(addr), evmGasLeft) diff --git a/system-contracts/contracts/precompiles/CodeOracle.yul b/system-contracts/contracts/precompiles/CodeOracle.yul index 836320bda..1e22e1662 100644 --- a/system-contracts/contracts/precompiles/CodeOracle.yul +++ b/system-contracts/contracts/precompiles/CodeOracle.yul @@ -32,9 +32,9 @@ object "CodeOracle" { /// @param versionedHash The versioned hash to check /// @return Whether the versioned hash is known function isCodeHashKnown(versionedHash) -> ret { - // 1. Selector for `KnwonCodesStorage.getMarker(bytes32)` + // 1. Selector for `KnownCodesStorage.getMarker(bytes32)` mstore(0, 0x4c6314f000000000000000000000000000000000000000000000000000000000) - // 2. Input for `KnwonCodesStorage.getMarker(bytes32)` + // 2. Input for `KnownCodesStorage.getMarker(bytes32)` mstore(4, versionedHash) let success := staticcall( From 6a9d83562efd64d567e34b25f42be196c0a8a139 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 20 Aug 2024 12:10:07 -0300 Subject: [PATCH 11/59] Remove evm constants contract --- system-contracts/contracts/EvmConstants.sol | 4 ---- system-contracts/contracts/EvmGasManager.sol | 2 -- 2 files changed, 6 deletions(-) delete mode 100644 system-contracts/contracts/EvmConstants.sol diff --git a/system-contracts/contracts/EvmConstants.sol b/system-contracts/contracts/EvmConstants.sol deleted file mode 100644 index 0873c5a9f..000000000 --- a/system-contracts/contracts/EvmConstants.sol +++ /dev/null @@ -1,4 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -uint256 constant GAS_DIVISOR = 1; diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index e9ae9ae47..bf6740257 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "./EvmConstants.sol"; - import {ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "./Constants.sol"; // We consider all the contracts (including system ones) as warm. From cb3ad25f27a65c2d9a6e0c03c8717f482017ca15 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:55:58 -0300 Subject: [PATCH 12/59] Remove asserts from bootloader (#26) --- system-contracts/bootloader/bootloader.yul | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/system-contracts/bootloader/bootloader.yul b/system-contracts/bootloader/bootloader.yul index b31246a9a..412a30d26 100644 --- a/system-contracts/bootloader/bootloader.yul +++ b/system-contracts/bootloader/bootloader.yul @@ -3205,9 +3205,8 @@ object "Bootloader" { assertEq(gt(getFrom(innerTxDataOffset), MAX_SYSTEM_CONTRACT_ADDR()), 1, "from in kernel space") - assertEq(getReserved0(innerTxDataOffset), 0, "reserved0 non zero") - assertEq(getReserved1(innerTxDataOffset), 0, "reserved1 non zero") + //assertEq(getReserved1(innerTxDataOffset), 0, "reserved1 non zero") assertEq(getReserved2(innerTxDataOffset), 0, "reserved2 non zero") assertEq(getReserved3(innerTxDataOffset), 0, "reserved3 non zero") assertEq(getFactoryDepsBytesLength(innerTxDataOffset), 0, "factory deps non zero") @@ -3230,7 +3229,7 @@ object "Bootloader" { assertEq(getReserved0(innerTxDataOffset), 0, "reserved0 non zero") - assertEq(getReserved1(innerTxDataOffset), 0, "reserved1 non zero") + //assertEq(getReserved1(innerTxDataOffset), 0, "reserved1 non zero") assertEq(getReserved2(innerTxDataOffset), 0, "reserved2 non zero") assertEq(getReserved3(innerTxDataOffset), 0, "reserved3 non zero") assertEq(getFactoryDepsBytesLength(innerTxDataOffset), 0, "factory deps non zero") @@ -3249,7 +3248,7 @@ object "Bootloader" { assertEq(gt(getFrom(innerTxDataOffset), MAX_SYSTEM_CONTRACT_ADDR()), 1, "from in kernel space") assertEq(getReserved0(innerTxDataOffset), 0, "reserved0 non zero") - assertEq(getReserved1(innerTxDataOffset), 0, "reserved1 non zero") + //assertEq(getReserved1(innerTxDataOffset), 0, "reserved1 non zero") assertEq(getReserved2(innerTxDataOffset), 0, "reserved2 non zero") assertEq(getReserved3(innerTxDataOffset), 0, "reserved3 non zero") } From 7d8300be3873f11c0f44b010a5117fb1abae15a3 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 21 Aug 2024 11:32:34 -0300 Subject: [PATCH 13/59] Remove old contracts constants not longer used --- .../libraries/SystemContractHelper.sol | 25 +------------------ .../libraries/SystemContractsCaller.sol | 4 --- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/system-contracts/contracts/libraries/SystemContractHelper.sol b/system-contracts/contracts/libraries/SystemContractHelper.sol index 400b399db..92bc4e1e1 100644 --- a/system-contracts/contracts/libraries/SystemContractHelper.sol +++ b/system-contracts/contracts/libraries/SystemContractHelper.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.20; import {MAX_SYSTEM_CONTRACT_ADDRESS} from "../Constants.sol"; import {Utils} from "./Utils.sol"; -import {SystemContractsCaller, CalldataForwardingMode, CALLFLAGS_CALL_ADDRESS, CODE_ADDRESS_CALL_ADDRESS, EVENT_WRITE_ADDRESS, EVENT_INITIALIZE_ADDRESS, GET_EXTRA_ABI_DATA_ADDRESS, LOAD_CALLDATA_INTO_ACTIVE_PTR_CALL_ADDRESS, META_CODE_SHARD_ID_OFFSET, META_CALLER_SHARD_ID_OFFSET, META_SHARD_ID_OFFSET, META_AUX_HEAP_SIZE_OFFSET, META_HEAP_SIZE_OFFSET, META_PUBDATA_PUBLISHED_OFFSET, META_CALL_ADDRESS, PTR_CALLDATA_CALL_ADDRESS, PTR_ADD_INTO_ACTIVE_CALL_ADDRESS, PTR_SHRINK_INTO_ACTIVE_CALL_ADDRESS, PTR_PACK_INTO_ACTIVE_CALL_ADDRESS, PRECOMPILE_CALL_ADDRESS, SET_CONTEXT_VALUE_CALL_ADDRESS, TO_L1_CALL_ADDRESS, MIMIC_CALL_CALL_ADDRESS, PTR_DATA_SIZE, PTR_DATA_COPY, LOAD_LATEST_RETURNDATA_INTO_ACTIVE_PTR_CALL_ADDRESS} from "./SystemContractsCaller.sol"; +import {SystemContractsCaller, CalldataForwardingMode, CALLFLAGS_CALL_ADDRESS, CODE_ADDRESS_CALL_ADDRESS, EVENT_WRITE_ADDRESS, EVENT_INITIALIZE_ADDRESS, GET_EXTRA_ABI_DATA_ADDRESS, LOAD_CALLDATA_INTO_ACTIVE_PTR_CALL_ADDRESS, META_CODE_SHARD_ID_OFFSET, META_CALLER_SHARD_ID_OFFSET, META_SHARD_ID_OFFSET, META_AUX_HEAP_SIZE_OFFSET, META_HEAP_SIZE_OFFSET, META_PUBDATA_PUBLISHED_OFFSET, META_CALL_ADDRESS, PTR_CALLDATA_CALL_ADDRESS, PTR_ADD_INTO_ACTIVE_CALL_ADDRESS, PTR_SHRINK_INTO_ACTIVE_CALL_ADDRESS, PTR_PACK_INTO_ACTIVE_CALL_ADDRESS, PRECOMPILE_CALL_ADDRESS, SET_CONTEXT_VALUE_CALL_ADDRESS, TO_L1_CALL_ADDRESS, MIMIC_CALL_CALL_ADDRESS} from "./SystemContractsCaller.sol"; import {IndexOutOfBounds, FailedToChargeGas} from "../SystemContractErrors.sol"; uint256 constant UINT32_MASK = type(uint32).max; @@ -394,27 +394,4 @@ library SystemContractHelper { success := call(to, callAddr, 0, farCallAbi, whoToMimic, 0, 0) } } - - function getActivePtrDataSize() internal view returns (uint256 size) { - address callAddr = PTR_DATA_SIZE; - - assembly { - size := staticcall(0, callAddr, 0, 0xFFFF, 0, 0) - } - } - - function copyActivePtrData(uint256 _dest, uint256 _source, uint256 _size) internal view { - address callAddr = PTR_DATA_COPY; - - assembly { - pop(staticcall(_dest, callAddr, _source, _size, 0, 0)) - } - } - - function loadReturndataIntoActivePtr() internal view { - address callAddr = LOAD_LATEST_RETURNDATA_INTO_ACTIVE_PTR_CALL_ADDRESS; - assembly { - pop(staticcall(0, callAddr, 0, 0xFFFF, 0, 0)) - } - } } diff --git a/system-contracts/contracts/libraries/SystemContractsCaller.sol b/system-contracts/contracts/libraries/SystemContractsCaller.sol index 22ab31c6e..14f361c6f 100644 --- a/system-contracts/contracts/libraries/SystemContractsCaller.sol +++ b/system-contracts/contracts/libraries/SystemContractsCaller.sol @@ -37,10 +37,6 @@ address constant PTR_PACK_INTO_ACTIVE_CALL_ADDRESS = address((1 << 16) - 25); address constant MULTIPLICATION_HIGH_ADDRESS = address((1 << 16) - 26); address constant GET_EXTRA_ABI_DATA_ADDRESS = address((1 << 16) - 27); -address constant PTR_DATA_LOAD = address((1 << 16) - 28); -address constant PTR_DATA_COPY = address((1 << 16) - 29); -address constant PTR_DATA_SIZE = address((1 << 16) - 30); - // All the offsets are in bits uint256 constant META_PUBDATA_PUBLISHED_OFFSET = 0 * 8; uint256 constant META_HEAP_SIZE_OFFSET = 8 * 8; From e6b7a83ec8c64a1c7d7278ee7485336b61f71fc8 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 21 Aug 2024 13:05:36 -0300 Subject: [PATCH 14/59] Fix some typos and outdated comments --- .../contracts/state-transition/chain-deps/facets/Executor.sol | 1 - system-contracts/contracts/EvmGasManager.sol | 2 +- system-contracts/contracts/EvmInterpreter.yul | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol index 13131d6b7..a397f96f4 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol @@ -606,7 +606,6 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { s.zkPorterIsAvailable, s.l2BootloaderBytecodeHash, l2DefaultAccountBytecodeHash, - // VM 1.5.0 requires us to pass the EVM simulator code hash. For now it is the same as the default account. l2EvmSimulatorBytecodeHash ); } diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index bf6740257..81d52dc27 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -20,7 +20,7 @@ contract EvmGasManager { uint256 originalValue; } - // We dont care about the size, since none of it will be stored/pub;ushed anywya + // We dont care about the size, since none of it will be stored/published anyway. struct EVMStackFrameInfo { bool isStatic; uint256 passGas; diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmInterpreter.yul index faa6aff7e..71a9b09fc 100644 --- a/system-contracts/contracts/EvmInterpreter.yul +++ b/system-contracts/contracts/EvmInterpreter.yul @@ -52,7 +52,7 @@ object "EVMInterpreter" { blobLen := add(blobLen, sub(32, mod(blobLen, 32))) } - // Not it is divisible by 32, but we must make sure that the number of 32 byte words is odd + // Now it is divisible by 32, but we must make sure that the number of 32 byte words is odd if iszero(eq(mod(blobLen, 64), 32)) { blobLen := add(blobLen, 32) } From 4ba25a3cffefb5711e1ad4a490462cc84464d312 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 21 Aug 2024 13:05:43 -0300 Subject: [PATCH 15/59] Add interface for evm gas manager --- .../contracts/interfaces/IEvmGasManager.sol | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 system-contracts/contracts/interfaces/IEvmGasManager.sol diff --git a/system-contracts/contracts/interfaces/IEvmGasManager.sol b/system-contracts/contracts/interfaces/IEvmGasManager.sol new file mode 100644 index 000000000..27c4e59b4 --- /dev/null +++ b/system-contracts/contracts/interfaces/IEvmGasManager.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +interface IEvmGasManager { + // We need trust to use `storage` pointers + struct WarmAccountInfo { + bool isWarm; + } + + struct SlotInfo { + bool warm; + uint256 originalValue; + } + + // We dont care about the size, since none of it will be stored/pub;ushed anyway. + struct EVMStackFrameInfo { + bool isStatic; + uint256 passGas; + } + + function warmAccount(address account) external payable returns (bool wasWarm); + + function isSlotWarm(uint256 _slot) external view returns (bool); + + function warmSlot(uint256 _slot, uint256 _currentValue) external payable returns (bool, uint256); + + /* + The flow is the following: + When conducting call: + 1. caller calls to an EVM contract pushEVMFrame with the corresponding gas + 2. callee calls consumeEvmFrame to get the gas & make sure that subsequent callee won't be able to read it. + 3. callee sets the return gas + 4. callee calls popEVMFrame to return the gas to the caller & remove the frame + */ + + function pushEVMFrame(uint256 _passGas, bool _isStatic) external; + + function consumeEvmFrame() external returns (uint256 passGas, bool isStatic); + + function popEVMFrame() external; +} From 668bcac68f601da26d8458565fae4281fe195c5b Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 21 Aug 2024 13:37:18 -0300 Subject: [PATCH 16/59] Simplify check for warm slots in evm gas manager --- system-contracts/contracts/EvmGasManager.sol | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index 81d52dc27..49d76745e 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -91,7 +91,14 @@ contract EvmGasManager { } function isSlotWarm(uint256 _slot) external view returns (bool) { - return tloadWarmSlot(msg.sender, _slot).warm; + SlotInfo storage ptr = warmSlots[msg.sender][_slot]; + bool isWarm; + + assembly { + isWarm := tload(ptr.slot) + } + + return isWarm; } function warmSlot(uint256 _slot, uint256 _currentValue) external payable onlySystemEvm returns (bool, uint256) { From 2c59ee8d80d72d1a2d4b9632112480c35c2bee27 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 21 Aug 2024 13:43:22 -0300 Subject: [PATCH 17/59] Check nonce equals zero for evm deploy --- system-contracts/contracts/ContractDeployer.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 41781d64f..f64dd46ee 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -350,7 +350,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { function _evmDeployOnAddress(address _newAddress, bytes calldata _initCode) internal { // Unfortunately we can not provide revert reason as it would break EVM compatibility - // TODO: maybe it is redundant + require(NONCE_HOLDER_SYSTEM_CONTRACT.getRawNonce(_newAddress) == 0x0); require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.getCodeHash(uint256(uint160(_newAddress))) == 0x0); _performDeployOnAddressEVM(_newAddress, AccountAbstractionVersion.None, _initCode, false); } From fbc8f8f67638375dfc35e9392396c5f779c2cb4f Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 21 Aug 2024 15:53:49 -0300 Subject: [PATCH 18/59] Fix trivial lint checks --- .../dev-contracts/test/CustomUpgradeTest.sol | 7 ++++++- .../dev-contracts/test/ExecutorProvingTest.sol | 6 +++++- .../contracts/upgrades/BaseZkSyncUpgrade.sol | 14 ++++++++++++-- l1-contracts/scripts/utils.ts | 4 +--- l1-contracts/src.ts/deploy.ts | 2 +- l1-contracts/src.ts/diamondCut.ts | 2 +- .../chain-deps/DiamondInit/Initialize.t.sol | 2 +- .../test/unit_tests/l2-upgrade.test.spec.ts | 2 +- system-contracts/contracts/ContractDeployer.sol | 13 ++++++------- system-contracts/contracts/NonceHolder.sol | 2 +- system-contracts/contracts/libraries/Utils.sol | 2 +- system-contracts/scripts/deploy-preimages.ts | 6 +++--- 12 files changed, 39 insertions(+), 23 deletions(-) diff --git a/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol b/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol index 317c531bd..c1c3d2f4c 100644 --- a/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol +++ b/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol @@ -31,7 +31,12 @@ contract CustomUpgradeTest is BaseZkSyncUpgrade { (uint32 newMinorVersion, bool isPatchOnly) = _setNewProtocolVersion(_proposedUpgrade.newProtocolVersion); _upgradeL1Contract(_proposedUpgrade.l1ContractsUpgradeCalldata); _upgradeVerifier(_proposedUpgrade.verifier, _proposedUpgrade.verifierParams); - _setBaseSystemContracts(_proposedUpgrade.bootloaderHash, _proposedUpgrade.defaultAccountHash, _proposedUpgrade.evmSimulatorHash, isPatchOnly); + _setBaseSystemContracts( + _proposedUpgrade.bootloaderHash, + _proposedUpgrade.defaultAccountHash, + _proposedUpgrade.evmSimulatorHash, + isPatchOnly + ); bytes32 txHash; txHash = _setL2SystemContractUpgrade( diff --git a/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol b/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol index adc528751..1ff8fc2b6 100644 --- a/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol +++ b/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol @@ -33,7 +33,11 @@ contract ExecutorProvingTest is ExecutorFacet { } /// Sets the DefaultAccount Hash and Bootloader Hash. - function setHashes(bytes32 l2DefaultAccountBytecodeHash, bytes32 l2BootloaderBytecodeHash, bytes32 l2EvmSimulatorBytecode) external { + function setHashes( + bytes32 l2DefaultAccountBytecodeHash, + bytes32 l2BootloaderBytecodeHash, + bytes32 l2EvmSimulatorBytecode + ) external { s.l2DefaultAccountBytecodeHash = l2DefaultAccountBytecodeHash; s.l2BootloaderBytecodeHash = l2BootloaderBytecodeHash; s.l2EvmSimulatorBytecodeHash = l2EvmSimulatorBytecode; diff --git a/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol b/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol index 1924f7252..aeded3905 100644 --- a/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol +++ b/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol @@ -82,7 +82,12 @@ abstract contract BaseZkSyncUpgrade is ZkSyncHyperchainBase { (uint32 newMinorVersion, bool isPatchOnly) = _setNewProtocolVersion(_proposedUpgrade.newProtocolVersion); _upgradeL1Contract(_proposedUpgrade.l1ContractsUpgradeCalldata); _upgradeVerifier(_proposedUpgrade.verifier, _proposedUpgrade.verifierParams); - _setBaseSystemContracts(_proposedUpgrade.bootloaderHash, _proposedUpgrade.defaultAccountHash, _proposedUpgrade.evmSimulatorHash, isPatchOnly); + _setBaseSystemContracts( + _proposedUpgrade.bootloaderHash, + _proposedUpgrade.defaultAccountHash, + _proposedUpgrade.evmSimulatorHash, + isPatchOnly + ); txHash = _setL2SystemContractUpgrade( _proposedUpgrade.l2ProtocolUpgradeTx, @@ -208,7 +213,12 @@ abstract contract BaseZkSyncUpgrade is ZkSyncHyperchainBase { /// @param _bootloaderHash The hash of the new bootloader bytecode. If zero, it will not be updated. /// @param _defaultAccountHash The hash of the new default account bytecode. If zero, it will not be updated. /// @param _patchOnly Whether only the patch part of the protocol version semver has changed. - function _setBaseSystemContracts(bytes32 _bootloaderHash, bytes32 _defaultAccountHash, bytes32 _evmSimulatorHash, bool _patchOnly) internal { + function _setBaseSystemContracts( + bytes32 _bootloaderHash, + bytes32 _defaultAccountHash, + bytes32 _evmSimulatorHash, + bool _patchOnly + ) internal { _setL2BootloaderBytecodeHash(_bootloaderHash, _patchOnly); _setL2DefaultAccountBytecodeHash(_defaultAccountHash, _patchOnly); _setL2EvmSimulatorBytecodeHash(_evmSimulatorHash, _patchOnly); diff --git a/l1-contracts/scripts/utils.ts b/l1-contracts/scripts/utils.ts index a012674b5..e60434a8f 100644 --- a/l1-contracts/scripts/utils.ts +++ b/l1-contracts/scripts/utils.ts @@ -72,9 +72,7 @@ export function readSystemContractsBytecode(fileName: string) { export function readEvmSimulatorbytecode() { const systemContractsPath = path.join(process.env.ZKSYNC_HOME as string, "contracts/system-contracts"); - return fs.readFileSync( - `${systemContractsPath}/contracts-preprocessed/artifacts/EvmInterpreter.yul.zbin` - ); + return fs.readFileSync(`${systemContractsPath}/contracts-preprocessed/artifacts/EvmInterpreter.yul.zbin`); } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/l1-contracts/src.ts/deploy.ts b/l1-contracts/src.ts/deploy.ts index 705c62b03..8bf5ef16a 100644 --- a/l1-contracts/src.ts/deploy.ts +++ b/l1-contracts/src.ts/deploy.ts @@ -81,7 +81,7 @@ export class Deployer { L2_DEFAULT_ACCOUNT_BYTECODE_HASH = config.defaultAccountBytecodeHash ? config.defaultAccountBytecodeHash : hexlify(hashL2Bytecode(readSystemContractsBytecode("DefaultAccount"))); - L2_EVM_SIMULATOR_BYTECODE_HASH = config.evmSimulatorBytecodeHash + L2_EVM_SIMULATOR_BYTECODE_HASH = config.evmSimulatorBytecodeHash ? config.evmSimulatorBytecodeHash : hexlify(hashL2Bytecode(readEvmSimulatorbytecode())); this.ownerAddress = config.ownerAddress != null ? config.ownerAddress : this.deployWallet.address; diff --git a/l1-contracts/src.ts/diamondCut.ts b/l1-contracts/src.ts/diamondCut.ts index 118b2c5df..99759fa46 100644 --- a/l1-contracts/src.ts/diamondCut.ts +++ b/l1-contracts/src.ts/diamondCut.ts @@ -35,7 +35,7 @@ export interface InitializeData { allowList: BigNumberish; l2BootloaderBytecodeHash: string; l2DefaultAccountBytecodeHash: string; - l2EvmSimulatorBytecodeHash: string, + l2EvmSimulatorBytecodeHash: string; priorityTxMaxGasLimit: BigNumberish; } diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/DiamondInit/Initialize.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/DiamondInit/Initialize.t.sol index 352b49891..cac368a2b 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/DiamondInit/Initialize.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/DiamondInit/Initialize.t.sol @@ -100,7 +100,7 @@ contract InitializeTest is DiamondInitTest { ); assertEq(utilsFacet.util_getL2BootloaderBytecodeHash(), initializeData.l2BootloaderBytecodeHash); assertEq(utilsFacet.util_getL2DefaultAccountBytecodeHash(), initializeData.l2DefaultAccountBytecodeHash); - assertEq(utilsFacet.util_getL2EvmSimulatorBytecodeHash();(), initializeData.l2EvmSimulatorBytecodeHash); + assertEq(utilsFacet.util_getL2EvmSimulatorBytecodeHash(), initializeData.l2EvmSimulatorBytecodeHash); assertEq(utilsFacet.util_getPriorityTxMaxGasLimit(), initializeData.priorityTxMaxGasLimit); assertEq( keccak256(abi.encode(utilsFacet.util_getFeeParams())), diff --git a/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts b/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts index 22b0ff8dc..1860863a5 100644 --- a/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts +++ b/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts @@ -502,7 +502,7 @@ describe.only("L2 upgrade test", function () { expect(upgradeEvents[3].args.newBytecodeHash).to.eq(bootloaderHash); expect(upgradeEvents[4].name).to.eq("NewL2DefaultAccountBytecodeHash"); - + expect(upgradeEvents[4].args.previousBytecodeHash).to.eq(L2_DEFAULT_ACCOUNT_BYTECODE_HASH); expect(upgradeEvents[4].args.newBytecodeHash).to.eq(defaultAccountHash); }); diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index f64dd46ee..e836680c6 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -1,10 +1,12 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +// solhint-disable reason-string, gas-custom-errors, func-named-parameters + +pragma solidity ^0.8.20; import {ImmutableData} from "./interfaces/IImmutableSimulator.sol"; import {IContractDeployer} from "./interfaces/IContractDeployer.sol"; -import {CREATE2_EVM_PREFIX, CREATE2_PREFIX, CREATE_PREFIX, NONCE_HOLDER_SYSTEM_CONTRACT, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT, FORCE_DEPLOYER, MAX_SYSTEM_CONTRACT_ADDRESS, KNOWN_CODE_STORAGE_CONTRACT, BASE_TOKEN_SYSTEM_CONTRACT, IMMUTABLE_SIMULATOR_SYSTEM_CONTRACT, COMPLEX_UPGRADER_CONTRACT, KECCAK256_SYSTEM_CONTRACT} from "./Constants.sol"; +import {CREATE2_PREFIX, CREATE_PREFIX, NONCE_HOLDER_SYSTEM_CONTRACT, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT, FORCE_DEPLOYER, MAX_SYSTEM_CONTRACT_ADDRESS, KNOWN_CODE_STORAGE_CONTRACT, BASE_TOKEN_SYSTEM_CONTRACT, IMMUTABLE_SIMULATOR_SYSTEM_CONTRACT, COMPLEX_UPGRADER_CONTRACT} from "./Constants.sol"; import {Utils} from "./libraries/Utils.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; @@ -12,8 +14,6 @@ import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; import {SystemContractBase} from "./abstract/SystemContractBase.sol"; import {Unauthorized, InvalidNonceOrderingChange, ValueMismatch, EmptyBytes32, NotAllowedToDeployInKernelSpace, HashIsNonZero, NonEmptyAccount, UnknownCodeHash, NonEmptyMsgValue} from "./SystemContractErrors.sol"; -import {RLPEncoder} from "./libraries/RLPEncoder.sol"; - /** * @author Matter Labs * @custom:security-contact security@matterlabs.dev @@ -352,7 +352,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { // Unfortunately we can not provide revert reason as it would break EVM compatibility require(NONCE_HOLDER_SYSTEM_CONTRACT.getRawNonce(_newAddress) == 0x0); require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.getCodeHash(uint256(uint160(_newAddress))) == 0x0); - _performDeployOnAddressEVM(_newAddress, AccountAbstractionVersion.None, _initCode, false); + _performDeployOnAddressEVM(_newAddress, AccountAbstractionVersion.None, _initCode); } /// @notice Deploy a certain bytecode on the address. @@ -410,8 +410,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { function _performDeployOnAddressEVM( address _newAddress, AccountAbstractionVersion _aaVersion, - bytes calldata _input, - bool _callConstructor + bytes calldata _input ) internal { AccountInfo memory newAccountInfo; newAccountInfo.supportedAAVersion = _aaVersion; diff --git a/system-contracts/contracts/NonceHolder.sol b/system-contracts/contracts/NonceHolder.sol index af91f87ae..4597e240b 100644 --- a/system-contracts/contracts/NonceHolder.sol +++ b/system-contracts/contracts/NonceHolder.sol @@ -6,7 +6,7 @@ import {INonceHolder} from "./interfaces/INonceHolder.sol"; import {IContractDeployer} from "./interfaces/IContractDeployer.sol"; import {SystemContractBase} from "./abstract/SystemContractBase.sol"; import {DEPLOYER_SYSTEM_CONTRACT, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "./Constants.sol"; -import {NonceIncreaseError, ZeroNonceError, NonceJumpError, ValueMismatch, NonceAlreadyUsed, NonceNotUsed, Unauthorized} from "./SystemContractErrors.sol"; +import {NonceIncreaseError, ZeroNonceError, NonceJumpError, ValueMismatch, NonceAlreadyUsed, NonceNotUsed} from "./SystemContractErrors.sol"; /** * @author Matter Labs diff --git a/system-contracts/contracts/libraries/Utils.sol b/system-contracts/contracts/libraries/Utils.sol index 16fd7ed4b..a6224cbb4 100644 --- a/system-contracts/contracts/libraries/Utils.sol +++ b/system-contracts/contracts/libraries/Utils.sol @@ -127,7 +127,7 @@ library Utils { } // the real max supported number is 2^16, but we'll stick to evm convention - uint256 constant MAX_EVM_BYTECODE_LENGTH = (2 ** 16) - 1; + uint256 internal constant MAX_EVM_BYTECODE_LENGTH = (2 ** 16) - 1; function hashEVMBytecode(bytes memory _bytecode) internal view returns (bytes32 hashedEVMBytecode) { require(_bytecode.length <= MAX_EVM_BYTECODE_LENGTH, "po"); diff --git a/system-contracts/scripts/deploy-preimages.ts b/system-contracts/scripts/deploy-preimages.ts index 7d4ca929e..245e0a9f4 100644 --- a/system-contracts/scripts/deploy-preimages.ts +++ b/system-contracts/scripts/deploy-preimages.ts @@ -158,14 +158,14 @@ class ZkSyncDeployer { return await zkSync.getL2BootloaderBytecodeHash(); } - // Returns the current default evm simulator bytecode on zkSync + // Returns the current default evm simulator bytecode on zkSync async currentEvmSimulatorBytecode(): Promise { const zkSync = await this.deployer.zkWallet.getMainContract(); return await zkSync.getL2EvmSimulatorBytecodeHash(); } - // If needed, appends the evm simulator bytecode to the upgrade - async checkShouldUpgradeEvmSimulator(evmSimulatorBytecode: string) { + // If needed, appends the evm simulator bytecode to the upgrade + async checkShouldUpgradeEvmSimulator(evmSimulatorBytecode: string) { const bytecodeHash = ethers.utils.hexlify(hashBytecode(evmSimulatorBytecode)); const currentEvmSimulatorBytecode = ethers.utils.hexlify(await this.currentEvmSimulatorBytecode()); From ef1affde8f449a14ddea581c8ee3f8a2f5b83b0a Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 21 Aug 2024 15:56:38 -0300 Subject: [PATCH 19/59] Disable some solidity hints for conflicting system contracts --- l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol | 2 ++ system-contracts/contracts/EvmGasManager.sol | 3 +++ system-contracts/contracts/NonceHolder.sol | 2 ++ system-contracts/contracts/SystemContext.sol | 2 ++ system-contracts/contracts/libraries/SystemContractHelper.sol | 3 +++ system-contracts/contracts/libraries/Utils.sol | 3 +++ 6 files changed, 15 insertions(+) diff --git a/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol b/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol index aeded3905..b4c941989 100644 --- a/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol +++ b/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT +// solhint-disable reason-string, gas-custom-errors + pragma solidity 0.8.24; import {SafeCast} from "@openzeppelin/contracts-v4/utils/math/SafeCast.sol"; diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index 49d76745e..de87426c5 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -1,4 +1,7 @@ // SPDX-License-Identifier: MIT + +// solhint-disable reason-string, gas-custom-errors + pragma solidity ^0.8.0; import {ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "./Constants.sol"; diff --git a/system-contracts/contracts/NonceHolder.sol b/system-contracts/contracts/NonceHolder.sol index 4597e240b..d7171d78b 100644 --- a/system-contracts/contracts/NonceHolder.sol +++ b/system-contracts/contracts/NonceHolder.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT +// solhint-disable reason-string, gas-custom-errors + pragma solidity 0.8.20; import {INonceHolder} from "./interfaces/INonceHolder.sol"; diff --git a/system-contracts/contracts/SystemContext.sol b/system-contracts/contracts/SystemContext.sol index cecd2e699..4f35641c0 100644 --- a/system-contracts/contracts/SystemContext.sol +++ b/system-contracts/contracts/SystemContext.sol @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT +// solhint-disable reason-string, gas-custom-errors + pragma solidity 0.8.20; import {ISystemContext} from "./interfaces/ISystemContext.sol"; diff --git a/system-contracts/contracts/libraries/SystemContractHelper.sol b/system-contracts/contracts/libraries/SystemContractHelper.sol index 92bc4e1e1..777d32c46 100644 --- a/system-contracts/contracts/libraries/SystemContractHelper.sol +++ b/system-contracts/contracts/libraries/SystemContractHelper.sol @@ -1,4 +1,7 @@ // SPDX-License-Identifier: MIT + +// solhint-disable func-named-parameters + // We use a floating point pragma here so it can be used within other projects that interact with the zkSync ecosystem without using our exact pragma version. pragma solidity ^0.8.20; diff --git a/system-contracts/contracts/libraries/Utils.sol b/system-contracts/contracts/libraries/Utils.sol index a6224cbb4..048e1284c 100644 --- a/system-contracts/contracts/libraries/Utils.sol +++ b/system-contracts/contracts/libraries/Utils.sol @@ -1,4 +1,7 @@ // SPDX-License-Identifier: MIT + +// solhint-disable gas-custom-errors + // We use a floating point pragma here so it can be used within other projects that interact with the zkSync ecosystem without using our exact pragma version. pragma solidity ^0.8.20; From b1c7e009d3ee505b18a18831ab966d195e6cf241 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Wed, 21 Aug 2024 17:05:49 -0300 Subject: [PATCH 20/59] Fix most of the l1 contracts foundry tests --- .../test/foundry/unit/concrete/DiamondCut/UpgradeLogic.t.sol | 2 +- .../foundry/unit/concrete/Executor/_Executor_Shared.t.sol | 2 +- l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol | 4 ++-- .../chain-deps/facets/Admin/ExecuteUpgrade.t.sol | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/l1-contracts/test/foundry/unit/concrete/DiamondCut/UpgradeLogic.t.sol b/l1-contracts/test/foundry/unit/concrete/DiamondCut/UpgradeLogic.t.sol index f0e5d8b62..1ee6bcebd 100644 --- a/l1-contracts/test/foundry/unit/concrete/DiamondCut/UpgradeLogic.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/DiamondCut/UpgradeLogic.t.sol @@ -91,7 +91,7 @@ contract UpgradeLogicTest is DiamondCutTest { // zkPorterIsAvailable: false, l2BootloaderBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, l2DefaultAccountBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, - l2EvmBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, + l2EvmSimulatorBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, priorityTxMaxGasLimit: 500000, // priority tx max L2 gas limit // initialProtocolVersion: 0, feeParams: FeeParams({ diff --git a/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol b/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol index aa8190ae8..18fb220e4 100644 --- a/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol @@ -67,7 +67,7 @@ contract ExecutorTest is Test { } function getGettersSelectors() public view returns (bytes4[] memory) { - bytes4[] memory selectors = new bytes4[](29); + bytes4[] memory selectors = new bytes4[](30); selectors[0] = getters.getVerifier.selector; selectors[1] = getters.getAdmin.selector; selectors[2] = getters.getPendingAdmin.selector; diff --git a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol index 595e119b2..260bc085a 100644 --- a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol +++ b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol @@ -210,7 +210,7 @@ library Utils { } function getGettersSelectors() public pure returns (bytes4[] memory) { - bytes4[] memory selectors = new bytes4[](29); + bytes4[] memory selectors = new bytes4[](30); selectors[0] = GettersFacet.getVerifier.selector; selectors[1] = GettersFacet.getAdmin.selector; selectors[2] = GettersFacet.getPendingAdmin.selector; @@ -258,7 +258,7 @@ library Utils { } function getUtilsFacetSelectors() public pure returns (bytes4[] memory) { - bytes4[] memory selectors = new bytes4[](41); + bytes4[] memory selectors = new bytes4[](43); selectors[0] = UtilsFacet.util_setChainId.selector; selectors[1] = UtilsFacet.util_getChainId.selector; selectors[2] = UtilsFacet.util_setBridgehub.selector; diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Admin/ExecuteUpgrade.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Admin/ExecuteUpgrade.t.sol index d09b6f204..71ccfc581 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Admin/ExecuteUpgrade.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Admin/ExecuteUpgrade.t.sol @@ -45,6 +45,7 @@ contract ExecuteUpgradeTest is AdminTest { factoryDeps: new bytes[](0), bootloaderHash: bytes32(0), defaultAccountHash: bytes32(0), + evmSimulatorHash: bytes32(0), verifier: address(0), verifierParams: verifierParams, l1ContractsUpgradeCalldata: hex"", From e37175dfa15f4fcd9e34da13331b8cd843645509 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:20:05 -0300 Subject: [PATCH 21/59] Change test hashes --- .../unit/concrete/Executor/ExecutorProof.t.sol | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol b/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol index a4934c80e..9f9e3786c 100644 --- a/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol @@ -75,12 +75,12 @@ contract ExecutorProofTest is Test { /// This test is based on a block generated in a local system. function test_Hashes() public { utilsFacet.util_setL2DefaultAccountBytecodeHash( - 0x0100058deb36e1f2eeb48bf3846d0e8eb38e9176754b73116bb41a472459a4dd + 0x0100058d1abd41a9984b37939862f99c18237dc6951c3d5a3d81593c798a8f81 ); utilsFacet.util_setL2EvmSimulatorBytecodeHash( - 0x01000f197081a9906cc411d0698c4961aeb5c74877f37f7071681da6e8ef3f31 + 0x01000f196acd122635a752fcb275be0cc95fd3bba348c1d0908a517fe316418e ); - utilsFacet.util_setL2BootloaderBytecodeHash(0x010008e7894d0dd14681c76bdb4d5e4e7f6b51bfe40c957d50eed3fec829fdb0); + utilsFacet.util_setL2BootloaderBytecodeHash(0x010008ddde4acc465cde1c420883701caadb41954567c0b4e3a0d1093a7afde7); utilsFacet.util_setZkPorterAvailability(false); IExecutor.CommitBatchInfo memory nextBatch = IExecutor.CommitBatchInfo({ @@ -89,7 +89,7 @@ contract ExecutorProofTest is Test { // ignored timestamp: 100, indexRepeatedStorageChanges: 84, - newStateRoot: 0x9cf7bb72401a56039ca097cabed20a72221c944ed9b0e515c083c04663ab45a6, + newStateRoot: 0x1df8761352f4d39602beaf619e6b7a96111d3a54550bcf21f2623860cf3ed3d8, // ignored numberOfLayer1Txs: 10, // ignored @@ -121,12 +121,12 @@ contract ExecutorProofTest is Test { ); assertEq( nextCommitment, - 0xa1dcde434352cda8e331e721232ff2d457d4074efae1e3d06ef5b10ffada0c9a, + 0x3073bec0e225ab1e393420a8458f386b76f6e7ba784a2fbcc0ea24a6fd6a32a1, "nextCommitment computation failed" ); - bytes32 prevCommitment = 0x6ebf945305689a8c3ac993df7f002d41d311a762cd6bf39bb054ead8d1f54404; + bytes32 prevCommitment = 0x8199d18dbc01ea80a635f515d6a12312daa1aa32b5404944477dcd41fd7b2bdf; uint256 result = executor.getBatchProofPublicInput(prevCommitment, nextCommitment); - assertEq(result, 0xAC7931F2C11013FC24963E41B86E5325A79F1150350CB41E4F0876A7, "getBatchProofPublicInput"); + assertEq(result, 4788207466353486800513567418370563062194355012625279630180492433957, "getBatchProofPublicInput"); } } From cd2babb79aeacd63e5873d46fdf7c9ba732d0925 Mon Sep 17 00:00:00 2001 From: Gianbelinche <39842759+gianbelinche@users.noreply.github.com> Date: Thu, 22 Aug 2024 10:00:06 -0300 Subject: [PATCH 22/59] Fix hardhat tests --- l1-contracts/src.ts/utils.ts | 1 + l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/l1-contracts/src.ts/utils.ts b/l1-contracts/src.ts/utils.ts index a5a915efd..5955f0497 100644 --- a/l1-contracts/src.ts/utils.ts +++ b/l1-contracts/src.ts/utils.ts @@ -136,6 +136,7 @@ export interface ProposedUpgrade { factoryDeps: BytesLike[]; bootloaderHash: BytesLike; defaultAccountHash: BytesLike; + evmSimulatorHash: BytesLike; verifier: string; verifierParams: VerifierParams; l1ContractsUpgradeCalldata: BytesLike; diff --git a/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts b/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts index 1860863a5..96d00a531 100644 --- a/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts +++ b/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts @@ -948,6 +948,7 @@ function buildProposeUpgrade(proposedUpgrade: PartialProposedUpgrade): ProposedU l2ProtocolUpgradeTx: buildL2CanonicalTransaction({ nonce: newProtocolVersion }), bootloaderHash: ethers.constants.HashZero, defaultAccountHash: ethers.constants.HashZero, + evmSimulatorHash: ethers.constants.HashZero, verifier: ethers.constants.AddressZero, verifierParams: buildVerifierParams({}), l1ContractsUpgradeCalldata: "0x", From 2f1181f3a85e4e489b75606eaafbae35f1c451c4 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 22 Aug 2024 12:56:43 -0300 Subject: [PATCH 23/59] Use modifier in evm gas manager to only modify callstack by system env --- system-contracts/contracts/EvmGasManager.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index de87426c5..3831a4ab4 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -128,13 +128,13 @@ contract EvmGasManager { 4. callee calls popEVMFrame to return the gas to the caller & remove the frame */ - function pushEVMFrame(uint256 _passGas, bool _isStatic) external { + function pushEVMFrame(uint256 _passGas, bool _isStatic) onlySystemEvm external { EVMStackFrameInfo memory frame = EVMStackFrameInfo({passGas: _passGas, isStatic: _isStatic}); evmStackFrames.push(frame); } - function consumeEvmFrame() external returns (uint256 passGas, bool isStatic) { + function consumeEvmFrame() onlySystemEvm external returns (uint256 passGas, bool isStatic) { if (evmStackFrames.length == 0) return (INF_PASS_GAS, false); EVMStackFrameInfo memory frameInfo = evmStackFrames[evmStackFrames.length - 1]; @@ -146,7 +146,7 @@ contract EvmGasManager { evmStackFrames[evmStackFrames.length - 1].passGas = INF_PASS_GAS; } - function popEVMFrame() external { + function popEVMFrame() onlySystemEvm external { evmStackFrames.pop(); } } From 59834ab66afcf2128b20b6c95186d0436c41e023 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Fri, 23 Aug 2024 16:31:40 -0300 Subject: [PATCH 24/59] Fix lint errores --- .../test/foundry/unit/concrete/Executor/ExecutorProof.t.sol | 6 +++++- system-contracts/contracts/EvmGasManager.sol | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol b/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol index 9f9e3786c..36cc60ac9 100644 --- a/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol @@ -127,6 +127,10 @@ contract ExecutorProofTest is Test { bytes32 prevCommitment = 0x8199d18dbc01ea80a635f515d6a12312daa1aa32b5404944477dcd41fd7b2bdf; uint256 result = executor.getBatchProofPublicInput(prevCommitment, nextCommitment); - assertEq(result, 4788207466353486800513567418370563062194355012625279630180492433957, "getBatchProofPublicInput"); + assertEq( + result, + 4788207466353486800513567418370563062194355012625279630180492433957, + "getBatchProofPublicInput" + ); } } diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index 3831a4ab4..80fe8f90c 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -128,13 +128,13 @@ contract EvmGasManager { 4. callee calls popEVMFrame to return the gas to the caller & remove the frame */ - function pushEVMFrame(uint256 _passGas, bool _isStatic) onlySystemEvm external { + function pushEVMFrame(uint256 _passGas, bool _isStatic) external onlySystemEvm { EVMStackFrameInfo memory frame = EVMStackFrameInfo({passGas: _passGas, isStatic: _isStatic}); evmStackFrames.push(frame); } - function consumeEvmFrame() onlySystemEvm external returns (uint256 passGas, bool isStatic) { + function consumeEvmFrame() external onlySystemEvm returns (uint256 passGas, bool isStatic) { if (evmStackFrames.length == 0) return (INF_PASS_GAS, false); EVMStackFrameInfo memory frameInfo = evmStackFrames[evmStackFrames.length - 1]; @@ -146,7 +146,7 @@ contract EvmGasManager { evmStackFrames[evmStackFrames.length - 1].passGas = INF_PASS_GAS; } - function popEVMFrame() onlySystemEvm external { + function popEVMFrame() external onlySystemEvm { evmStackFrames.pop(); } } From 1117c058cc7dd666954537e45fb34433b1001f8a Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Fri, 23 Aug 2024 18:13:33 -0300 Subject: [PATCH 25/59] Fix typos --- system-contracts/contracts/precompiles/CodeOracle.yul | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system-contracts/contracts/precompiles/CodeOracle.yul b/system-contracts/contracts/precompiles/CodeOracle.yul index 1e22e1662..f7e93803d 100644 --- a/system-contracts/contracts/precompiles/CodeOracle.yul +++ b/system-contracts/contracts/precompiles/CodeOracle.yul @@ -66,7 +66,7 @@ object "CodeOracle" { /// @param versionedHash The versioned hash to decommit. /// @param lenInWords The length of the data in bytes to decommit. function decommit(versionedHash, lenInWords) { - // The operation below are never expected to overflow since the `lenInWords` is a most 2 bytes long. + // The operation below are never expected to overflow since the `lenInWords` is at most 2 bytes long. let gasCost := mul(decommmitCostPerWord(), lenInWords) // The cost of the decommit operation can not exceed the maximum value of the `uint32` type. @@ -102,7 +102,7 @@ object "CodeOracle" { // To avoid the complexity of calculating the length of the preimage in circuits, the length of the pointer is always fixed to 2^21 bytes. // So the amount of data actually copied is determined here. // Note, that here we overwrite the first `lenInBytes` bytes of the memory, but it is fine since the written values are equivalent - // to the bytes previously written there by the `decommit` operation (in case this is the first page where the decomit happened). + // to the bytes previously written there by the `decommit` operation (in case this is the first page where the decommit happened). // In the future we won't do this and simply return the pointer returned by the `decommit` operation, shrunk to the `lenInBytes` length. verbatim_3i_0o("active_ptr_data_copy", 0, 0, lenInBytes) @@ -121,7 +121,7 @@ object "CodeOracle" { } let version := shr(248, versionedCodeHash) - // Currently, only a single version of the code hash is supported: + // Currently, two versions of the code hash is supported: // 1. The standard zkEVM bytecode. It has the following format: // - hash[0] -- version (0x01) // - hash[1] -- whether the contract is being constructed From 2579d6893efcdc7172953abb7f5a83bff58ed920 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Fri, 23 Aug 2024 18:16:02 -0300 Subject: [PATCH 26/59] Fix another typo --- system-contracts/contracts/precompiles/CodeOracle.yul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system-contracts/contracts/precompiles/CodeOracle.yul b/system-contracts/contracts/precompiles/CodeOracle.yul index f7e93803d..ea8513567 100644 --- a/system-contracts/contracts/precompiles/CodeOracle.yul +++ b/system-contracts/contracts/precompiles/CodeOracle.yul @@ -96,7 +96,7 @@ object "CodeOracle" { // decommit operation into the `active` pointer. verbatim_0i_0o("decommit_ptr_to_active") - // This operation is never expected to overflow since the `lenInWords` is a most 2 bytes long. + // This operation is never expected to overflow since the `lenInWords` is at most 2 bytes long. let lenInBytes := mul(lenInWords, 32) // To avoid the complexity of calculating the length of the preimage in circuits, the length of the pointer is always fixed to 2^21 bytes. From 0ecbe61e0794ae9e4c82ff230e13e14ea91d84a0 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Fri, 23 Aug 2024 19:03:54 -0300 Subject: [PATCH 27/59] Check for the `to` address to be zero when dispatching to createEVM on the `DefaultAccount` --- system-contracts/contracts/DefaultAccount.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system-contracts/contracts/DefaultAccount.sol b/system-contracts/contracts/DefaultAccount.sol index c3552c8f2..78197856f 100644 --- a/system-contracts/contracts/DefaultAccount.sol +++ b/system-contracts/contracts/DefaultAccount.sol @@ -140,7 +140,7 @@ contract DefaultAccount is IAccount { uint32 gas = Utils.safeCastToU32(gasleft()); // TODO: if possible, maybe implement some way to avoid memory copying here. - if (_transaction.reserved[1] != 0) { + if ((_transaction.reserved[1] != 0) && (to == address(0))) { DEPLOYER_SYSTEM_CONTRACT.createEVM{value: value}(data); return; } From 0ac46175e091586e6e23dcafda12b15009cbec7d Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Mon, 26 Aug 2024 12:10:11 -0300 Subject: [PATCH 28/59] Fix format --- l1-contracts/scripts/token-migration.ts | 8 ++++++-- l1-contracts/src.ts/deploy-utils.ts | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/l1-contracts/scripts/token-migration.ts b/l1-contracts/scripts/token-migration.ts index b18260ca3..1ea0d1a12 100644 --- a/l1-contracts/scripts/token-migration.ts +++ b/l1-contracts/scripts/token-migration.ts @@ -233,11 +233,15 @@ export async function transferTokensOnForkedNetwork(deployer: Deployer) { const erc20contract = IERC20Factory.connect(tokenAddress, provider); console.log(`Migrating token ${tokenAddress}`); console.log( - `Balance before: ${await erc20contract.balanceOf(deployer.addresses.Bridges.ERC20BridgeProxy)}, ${await erc20contract.balanceOf(deployer.addresses.Bridges.SharedBridgeProxy)}` + `Balance before: ${await erc20contract.balanceOf( + deployer.addresses.Bridges.ERC20BridgeProxy + )}, ${await erc20contract.balanceOf(deployer.addresses.Bridges.SharedBridgeProxy)}` ); await transferTokens(deployer, tokenAddress); console.log( - `Balance after: ${await erc20contract.balanceOf(deployer.addresses.Bridges.ERC20BridgeProxy)}, ${await erc20contract.balanceOf(deployer.addresses.Bridges.SharedBridgeProxy)}` + `Balance after: ${await erc20contract.balanceOf( + deployer.addresses.Bridges.ERC20BridgeProxy + )}, ${await erc20contract.balanceOf(deployer.addresses.Bridges.SharedBridgeProxy)}` ); } for (const tokenAddress of tokenList) { diff --git a/l1-contracts/src.ts/deploy-utils.ts b/l1-contracts/src.ts/deploy-utils.ts index 71b4d0c31..c431acc5e 100644 --- a/l1-contracts/src.ts/deploy-utils.ts +++ b/l1-contracts/src.ts/deploy-utils.ts @@ -72,7 +72,9 @@ export async function deployBytecodeViaCreate2( const gasUsed = receipt.gasUsed; log( - `${contractName} deployed, gasUsed: ${gasUsed.toString()}, tx hash: ${tx.hash}, expected address: ${expectedAddress}` + `${contractName} deployed, gasUsed: ${gasUsed.toString()}, tx hash: ${ + tx.hash + }, expected address: ${expectedAddress}` ); const deployedBytecodeAfter = await deployWallet.provider.getCode(expectedAddress); From 9cd43a218b4a18daed3d4f805bb3f22b1b946d28 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Mon, 26 Aug 2024 16:55:32 -0300 Subject: [PATCH 29/59] Update lock file --- yarn.lock | 111 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 49 deletions(-) diff --git a/yarn.lock b/yarn.lock index ec9fb4e4b..1de54180b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -756,9 +756,9 @@ dockerode "^3.3.4" "@matterlabs/hardhat-zksync-solc@^1.0.5", "@matterlabs/hardhat-zksync-solc@^1.1.4", "@matterlabs/hardhat-zksync-solc@^1.2.1": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-1.2.2.tgz#45daee64b56d322cfd896896f19fa8239c28bf0e" - integrity sha512-UutCzXuAKh1RDR4NnF5bjmSsDdiUvyzeiQxKTu+ul244bthK2aw0nMeMTeT7XJakrVuLm3futIZiOXQjPieKbw== + version "1.2.3" + resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-1.2.3.tgz#90fff87e36f3bf39e594686d8959111e40a5fff3" + integrity sha512-vRvA89DEV49vBcm1/lZVVp+k3OHjuFzhGnzzgwk9zmV9rr4onRDtTShPbu7fP6MdJOTZQ0F3f82rYKsh0ERqNA== dependencies: "@nomiclabs/hardhat-docker" "^2.0.2" chai "^4.3.4" @@ -886,6 +886,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@nolyfill/is-core-module@1.0.39": + version "1.0.39" + resolved "https://registry.yarnpkg.com/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz#3dc35ba0f1e66b403c00b39344f870298ebb1c8e" + integrity sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA== + "@nomicfoundation/edr-darwin-arm64@0.3.8": version "0.3.8" resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.8.tgz#09de1f03c0336670fce959f376f0fe9137545836" @@ -1024,9 +1029,9 @@ ordinal "^1.0.3" "@nomicfoundation/hardhat-ethers@^3.0.4": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.6.tgz#e8ba7f9719de360c03501b85dae4999bb3a7e1c5" - integrity sha512-/xzkFQAaHQhmIAYOQmvHBPwL+NkwLzT9gRZBsgWUYeV+E6pzXsBQsHfRYbAZ3XEYare+T7S+5Tg/1KDJgepSkA== + version "3.0.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.7.tgz#be90f79e96a22e6e982bca20ab0af05ed1f09c26" + integrity sha512-pxLWpDiqC208shoz/lMbVFbxcVxE+qIs8qDrwdcubWH99UO1p6uwXakMa36ICRfB/IEToSLDJGSsKhwY84feCQ== dependencies: debug "^4.1.1" lodash.isequal "^4.5.0" @@ -1349,11 +1354,11 @@ type-detect "4.0.8" "@sinonjs/fake-timers@^11.2.2": - version "11.2.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz#50063cc3574f4a27bd8453180a04171c85cc9699" - integrity sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw== + version "11.3.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz#51d6e8d83ca261ff02c0ab0e68e9db23d5cd5999" + integrity sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA== dependencies: - "@sinonjs/commons" "^3.0.0" + "@sinonjs/commons" "^3.0.1" "@sinonjs/samsam@^8.0.0": version "8.0.0" @@ -1486,9 +1491,9 @@ "@types/chai" "*" "@types/chai@*", "@types/chai@^4.2.21": - version "4.3.17" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.17.tgz#9195f9d242f2ac3b429908864b6b871a8f73f489" - integrity sha512-zmZ21EWzR71B4Sscphjief5djsLre50M6lI622OSySTmn9DB3j+C3kWroHfBQWXbOBwbgg/M8CG/hUxDLIloow== + version "4.3.18" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.18.tgz#dd6a46c9796b0435c13f85e8d44c8ea8e37fa2c1" + integrity sha512-2UfJzigyNa8kYTKn7o4hNMPphkxtu4WTJyobK3m4FBpyj7EK5xgtPcOtxLm7Dznk/Qxr0QXn+gQbkg7mCZKdfg== "@types/concat-stream@^1.6.0": version "1.6.1" @@ -1584,9 +1589,9 @@ form-data "^4.0.0" "@types/node@*": - version "22.4.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.4.1.tgz#9b595d292c65b94c20923159e2ce947731b6fdce" - integrity sha512-1tbpb9325+gPnKK0dMm+/LMriX0vKxf6RnB0SZUqfyVkQ4fMgUSySqhxE/y8Jvs4NyF1yHzTfG9KlnkIODxPKg== + version "22.5.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.0.tgz#10f01fe9465166b4cab72e75f60d8b99d019f958" + integrity sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg== dependencies: undici-types "~6.19.2" @@ -2130,9 +2135,9 @@ axios@^0.21.1: follow-redirects "^1.14.0" axios@^1.4.0, axios@^1.5.1, axios@^1.6.2, axios@^1.7.2: - version "1.7.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2" - integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw== + version "1.7.5" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.5.tgz#21eed340eb5daf47d29b6e002424b3e88c8c54b1" + integrity sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" @@ -3122,7 +3127,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enhanced-resolve@^5.12.0: +enhanced-resolve@^5.15.0: version "5.17.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== @@ -3295,22 +3300,23 @@ eslint-import-resolver-node@^0.3.9: resolve "^1.22.4" eslint-import-resolver-typescript@^3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa" - integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg== + version "3.6.3" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz#bb8e388f6afc0f940ce5d2c5fd4a3d147f038d9e" + integrity sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA== dependencies: - debug "^4.3.4" - enhanced-resolve "^5.12.0" - eslint-module-utils "^2.7.4" - fast-glob "^3.3.1" - get-tsconfig "^4.5.0" - is-core-module "^2.11.0" + "@nolyfill/is-core-module" "1.0.39" + debug "^4.3.5" + enhanced-resolve "^5.15.0" + eslint-module-utils "^2.8.1" + fast-glob "^3.3.2" + get-tsconfig "^4.7.5" + is-bun-module "^1.0.2" is-glob "^4.0.3" -eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" - integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== +eslint-module-utils@^2.8.0, eslint-module-utils@^2.8.1: + version "2.8.2" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz#2ecad69d71e1fa81f17f7f24d5d3e46b168de663" + integrity sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg== dependencies: debug "^3.2.7" @@ -3756,7 +3762,7 @@ fast-diff@^1.1.2, fast-diff@^1.2.0: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== -fast-glob@^3.0.3, fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.1, fast-glob@^3.3.2: +fast-glob@^3.0.3, fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -4061,7 +4067,7 @@ get-symbol-description@^1.0.2: es-errors "^1.3.0" get-intrinsic "^1.2.4" -get-tsconfig@^4.5.0: +get-tsconfig@^4.7.5: version "4.7.6" resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.6.tgz#118fd5b7b9bae234cc7705a00cd771d7eb65d62a" integrity sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA== @@ -4365,9 +4371,9 @@ hardhat@=2.22.2: ws "^7.4.6" hardhat@^2.14.0: - version "2.22.8" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.8.tgz#348dcdb48c44648ae7723f6efb511785e2b220c5" - integrity sha512-hPh2feBGRswkXkoXUFW6NbxgiYtEzp/3uvVFjYROy6fA9LH8BobUyxStlyhSKj4+v1Y23ZoUBOVWL84IcLACrA== + version "2.22.9" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.9.tgz#d8f2720561dc60f5cc0ee80c82f9b1907fd61c88" + integrity sha512-sWiuI/yRdFUPfndIvL+2H18Vs2Gav0XacCFYY5msT5dHOWkhLxESJySIk9j83mXL31aXL8+UMA9OgViFLexklg== dependencies: "@ethersproject/abi" "^5.1.2" "@metamask/eth-sig-util" "^4.0.0" @@ -4707,15 +4713,22 @@ is-buffer@^2.0.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== +is-bun-module@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-bun-module/-/is-bun-module-1.1.0.tgz#a66b9830869437f6cdad440ba49ab6e4dc837269" + integrity sha512-4mTAVPlrXpaN3jtF0lsnPCMGnq4+qZjVIKq0HCpfcqf8OC1SM5oATCIAPM5V5FN05qp2NNnFndphmdZS9CV3hA== + dependencies: + semver "^7.6.3" + is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1: - version "2.15.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.0.tgz#71c72ec5442ace7e76b306e9d48db361f22699ea" - integrity sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA== +is-core-module@^2.13.0, is-core-module@^2.13.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" + integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== dependencies: hasown "^2.0.2" @@ -5452,9 +5465,9 @@ micro-ftch@^0.3.1: integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== micromatch@^4.0.4: - version "4.0.7" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: braces "^3.0.3" picomatch "^2.3.1" @@ -6554,7 +6567,7 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.4, semver@^7.3.7, semver@^7.5.1, semver@^7.5.2, semver@^7.5.4, semver@^7.6.2: +semver@^7.3.4, semver@^7.3.7, semver@^7.5.1, semver@^7.5.2, semver@^7.5.4, semver@^7.6.2, semver@^7.6.3: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== @@ -7312,9 +7325,9 @@ tslib@^1.9.3: integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" - integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== tsort@0.0.1: version "0.0.1" From 6bdc84375de778c33592be9a3cf3dcf81e54ac46 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 27 Aug 2024 11:32:43 -0300 Subject: [PATCH 30/59] Fix compiler version for compile yul script --- system-contracts/scripts/compile-yul.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system-contracts/scripts/compile-yul.ts b/system-contracts/scripts/compile-yul.ts index 67b468987..6223b9362 100644 --- a/system-contracts/scripts/compile-yul.ts +++ b/system-contracts/scripts/compile-yul.ts @@ -12,7 +12,7 @@ import * as fs from "fs"; import { Command } from "commander"; import * as _path from "path"; -const COMPILER_VERSION = "1.3.18"; +const COMPILER_VERSION = "1.5.0"; const IS_COMPILER_PRE_RELEASE = true; const CONTRACTS_DIR = "contracts-preprocessed"; const BOOTLOADER_DIR = "bootloader"; @@ -22,7 +22,9 @@ const TIMESTAMP_FILE_BOOTLOADER = "last_compilation_bootloader.timestamp"; export async function compileYul(paths: CompilerPaths, file: string) { const solcCompilerPath = await getSolcLocation(); + console.log("COMPILING") const zksolcLocation = await compilerLocation(COMPILER_VERSION, IS_COMPILER_PRE_RELEASE); + console.log("zksolcLocation", zksolcLocation) await spawn( `${zksolcLocation} ${paths.absolutePathSources}/${file} --solc ${solcCompilerPath} --optimization 3 --system-mode --yul --bin --overwrite -o ${paths.absolutePathArtifacts}` ); From 7f6da78915b3d2bd0857d66f689bcb194aba34a7 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 27 Aug 2024 11:44:24 -0300 Subject: [PATCH 31/59] Delete debug logs --- system-contracts/scripts/compile-yul.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/system-contracts/scripts/compile-yul.ts b/system-contracts/scripts/compile-yul.ts index 6223b9362..e8d91622b 100644 --- a/system-contracts/scripts/compile-yul.ts +++ b/system-contracts/scripts/compile-yul.ts @@ -22,9 +22,7 @@ const TIMESTAMP_FILE_BOOTLOADER = "last_compilation_bootloader.timestamp"; export async function compileYul(paths: CompilerPaths, file: string) { const solcCompilerPath = await getSolcLocation(); - console.log("COMPILING") const zksolcLocation = await compilerLocation(COMPILER_VERSION, IS_COMPILER_PRE_RELEASE); - console.log("zksolcLocation", zksolcLocation) await spawn( `${zksolcLocation} ${paths.absolutePathSources}/${file} --solc ${solcCompilerPath} --optimization 3 --system-mode --yul --bin --overwrite -o ${paths.absolutePathArtifacts}` ); From ca6b3cb0eeaea6ff173a4d447a728d4d5edcbcef Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 27 Aug 2024 13:08:45 -0300 Subject: [PATCH 32/59] Download solc compiler when not found in cache --- system-contracts/scripts/utils.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system-contracts/scripts/utils.ts b/system-contracts/scripts/utils.ts index e06c14e50..21390eb02 100644 --- a/system-contracts/scripts/utils.ts +++ b/system-contracts/scripts/utils.ts @@ -207,6 +207,11 @@ export async function getSolcLocation(): Promise { const solcVersion = hre.config.solidity.compilers[0].version; + if (!await downloader.isCompilerDownloaded(solcVersion)) { + console.log(`Compiler ${solcVersion} not found, downloading...`); + await downloader.downloadCompiler(solcVersion, async () => false, async () => false); + } + return (await downloader.getCompiler(solcVersion))!.compilerPath; } From ad52dd8bc455a578d357ba26db7ef1b7fbe161aa Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 27 Aug 2024 13:19:07 -0300 Subject: [PATCH 33/59] Fix lint errors --- system-contracts/scripts/utils.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/system-contracts/scripts/utils.ts b/system-contracts/scripts/utils.ts index 21390eb02..b8188c0e4 100644 --- a/system-contracts/scripts/utils.ts +++ b/system-contracts/scripts/utils.ts @@ -207,9 +207,13 @@ export async function getSolcLocation(): Promise { const solcVersion = hre.config.solidity.compilers[0].version; - if (!await downloader.isCompilerDownloaded(solcVersion)) { + if (!(await downloader.isCompilerDownloaded(solcVersion))) { console.log(`Compiler ${solcVersion} not found, downloading...`); - await downloader.downloadCompiler(solcVersion, async () => false, async () => false); + await downloader.downloadCompiler( + solcVersion, + async () => {}, + async () => {} + ); } return (await downloader.getCompiler(solcVersion))!.compilerPath; From 01c0bd522ecaa4ffa00a49733bf6c7538355c89b Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 27 Aug 2024 14:45:11 -0300 Subject: [PATCH 34/59] Update contracts hashes --- system-contracts/SystemContractsHashes.json | 82 ++++++++++++--------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index e70d6c003..886b0b594 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,112 +3,119 @@ "contractName": "AccountCodeStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x0100005d39637f175e59ed8b149fb5767eaa1e1668ec9e884a13ad656c625748", - "sourceCodeHash": "0xcf59b8e87c4e6a45172938d0f991c301717556141e03a6c43f30db220b4b8093" + "bytecodeHash": "0x01000083d2aea30622e239d77e7af69e459f3e54a25d80f4bfcac94eebb92f35", + "sourceCodeHash": "0xd093d1595f6395c3d447c86e377d847690bcbd6b0e69488b4161286bf9e4ea82" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010007c72a6c3838b90ba1574a7f0b9ead2ccc53b7429e94055eb4e29f9cdd62", - "sourceCodeHash": "0x2605e2d28cf99dbde11aa545e7fa9b6343f988b7173283f7dfd54780e9947ce9" + "bytecodeHash": "0x010007e984aa274015d900d32e01f5ae34c346bb303cbcea5328fda4050bb328", + "sourceCodeHash": "0x8462a9ddedbff81c6cf8fc3ac33500f4f416fc31b1f025d90bb760fa4ebca8a4" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004dee09025db93936ca0913936a6ef363256c2427e7c6c646ea5aeb8631", + "bytecodeHash": "0x0100004deec68816dc8f01d94db0a6eb2d9623297a85767652db2aa3c9e3d363", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100014f7c7a4728b9960e1146b1ab129cf4df893f523a45bf2c1a6713ece7be", + "bytecodeHash": "0x010001534b9733c31d514e5c3a0017f86ff030a9bdbf3611e808c16072aaffc2", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010004e54238d31df887052849f439609045c2f21aa4e311e381be824749da74", - "sourceCodeHash": "0x2b52178555e74f3696f9ae08fdce14c6046c3b18e0f02f0187609ca8a3bba471" + "bytecodeHash": "0x010007534a7f55eee49ea99820c45d4e484a3192591e6613c87292565cfa8d41", + "sourceCodeHash": "0x3d6200608d8ee9ecd71f6d44f6e30197b0643374e225894c30f0b00d83e71bfb" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100004931dda7bd294161ad0ef0e228d4b4afc937cab9af4a2d938935fb6ea0", + "bytecodeHash": "0x01000057d0c12542ad9656d6581f114bbf2ef9f7681119eaeb601895776d552e", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100055da70d970f98ca4677a4b2fcecef5354f345cc5c6d13a78339e5fd87a9", - "sourceCodeHash": "0xebffe840ebbd9329edb1ebff8ca50f6935e7dabcc67194a896fcc2e968d46dfb" + "bytecodeHash": "0x010005ab0c1bd9cb04aaec180331f6eec79354413e5cfff9cf2076fdbb4b965b", + "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { "contractName": "EmptyContract", "bytecodePath": "artifacts-zk/contracts-preprocessed/EmptyContract.sol/EmptyContract.json", "sourceCodePath": "contracts-preprocessed/EmptyContract.sol", - "bytecodeHash": "0x010000078f32964c38fbd138a0369f4723f07ac6f4919c45ef738c18bf874ccd", + "bytecodeHash": "0x01000007bad04be2f33020fe006812a44718c6de4545c3357645b65debf6a18e", "sourceCodeHash": "0xcac36c5afafbcff83601f4fbfdff660aa66d8c80ed97b9322d3011c1926b554d" }, + { + "contractName": "EvmGasManager", + "bytecodePath": "artifacts-zk/contracts-preprocessed/EvmGasManager.sol/EvmGasManager.json", + "sourceCodePath": "contracts-preprocessed/EvmGasManager.sol", + "bytecodeHash": "0x010000ed0e7701f0ee1ab3e7f19096b6306321b92d9e1ddb63573450cf18d6b4", + "sourceCodeHash": "0x6e58be3f630adf305473e9a1844a448d9836322c10dc79e953a7ae319fc009b0" + }, { "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000039575b3cb0a5e96a80d89738a7cafa7e7995e7e4857f83c8982f5ff866", + "bytecodeHash": "0x01000039086bd8d011cdbee75bd5d8f353a068ac6d225d9660de7bebb86ec4e2", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x0100006f232f5cf3c8ffde9230c1af56f3129f69d9851a8d29751613a385418f", - "sourceCodeHash": "0xb39b5b81168653e0c5062f7b8e1d6d15a4e186df3317f192f0cb2fc3a74f5448" + "bytecodeHash": "0x010000cf9307e59e12fd3fb768da1783e89af637230ef50fd2eea7da3226ce01", + "sourceCodeHash": "0xe07e6543ac09b86042eff5f9067df6db10a4fc039ecb56098a882ee1019c3031" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010002956ca323790f0c8b855ccc115fe48fa127189d80de464eaf956acda5a3", + "bytecodeHash": "0x010002b1f8226eca1512e5be51f4515b4b2122ef644db81391c556aea0813cb8", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x0100010348a5ee59718d33426818b6d5a20a50efe68aecf7053304aeff82b7aa", + "bytecodeHash": "0x01000103333b0ca5b07895fff7974937705497f524588ce6d475aef277da1481", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005d426224423feeefe85bc7c7a02f65d01eb7e088c6978e421d78cfea72", + "bytecodeHash": "0x01000065d3f346bcd121e9b6ad7f883cb5cbfa982a0966fc24e318acb5d79c7e", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000d91567c5bd154d2350868fb366fbb131e51087799cc5da6a7bc9f40a92", - "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" + "bytecodeHash": "0x010001017915583cf42a949b1decaf1ef9df356f66a501b9a988cdff9d951bf6", + "sourceCodeHash": "0x9ec18b6a78758b999f9acdca50b1f2464beac1cb317b7184017fd4e96ad7ec58" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x0100004731b1807f406a678ca56a14d29917e2de60fca30cc7fa01169418f3ce", + "bytecodeHash": "0x0100004796b09e7f678de61de92079e0daeb0403d3dc70e34a7c688a63010af5", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a5a3730f0455b91c43e1b4cdd96cbffbdb60c161eb16586908a5e740d8", + "bytecodeHash": "0x010001ab2bab377b8c6f95801ca4ba783d549f8345712c1bc3bab84b967c79df", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { @@ -118,12 +125,19 @@ "bytecodeHash": "0x010000159a3a08da3ac57cdefec0e9e30da60456bc5643134cf16d6957bcf1ac", "sourceCodeHash": "0x55cfee65f174350edfd690c949bc0a29458f25da11f1d5f90b57621567df1fc3" }, + { + "contractName": "EvmInterpreter", + "bytecodePath": "contracts-preprocessed/artifacts/EvmInterpreter.yul.zbin", + "sourceCodePath": "contracts-preprocessed/EvmInterpreter.yul", + "bytecodeHash": "0x01000f196acd122635a752fcb275be0cc95fd3bba348c1d0908a517fe316418e", + "sourceCodeHash": "0x068f1229b92e0f3930231782f106a9889b8281b6750cca26d0375b6435d1fdaa" + }, { "contractName": "CodeOracle", "bytecodePath": "contracts-preprocessed/precompiles/artifacts/CodeOracle.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/CodeOracle.yul", - "bytecodeHash": "0x01000023b02bbb21baf1367835e56ae17b82688527dc8f78caf34b12e670ee65", - "sourceCodeHash": "0x55692fab0ef8b5bab3f6fb77aec84f3d1f1cdf97c0640b327d10594ea61218d2" + "bytecodeHash": "0x01000027f44f077c946fcd3326d4c809ce8dc83348dd24273a76f5d9d436044f", + "sourceCodeHash": "0x894815edd40d181d8b2e9f37271639c5110f5e4de0c139f103702ee8a7566483" }, { "contractName": "EcAdd", @@ -178,35 +192,35 @@ "contractName": "bootloader_test", "bytecodePath": "bootloader/build/artifacts/bootloader_test.yul.zbin", "sourceCodePath": "bootloader/build/bootloader_test.yul", - "bytecodeHash": "0x010003cbdea8040793e57c3584e3ef2fd3260caf9244d1ab22a64e8cf890b485", - "sourceCodeHash": "0x8fe3cf367c26e64e8bfb85f7488723bcf229e71ee6685dda6ee6ce9bc7d28cab" + "bytecodeHash": "0x010003cbe27a00667d83135f1db1dba76ca9d36b58125d38bd6b4182f7e4f938", + "sourceCodeHash": "0x193eee1c508be6af17148506bc010fbb72ed465fa072f0458232e602727ea6b1" }, { "contractName": "fee_estimate", "bytecodePath": "bootloader/build/artifacts/fee_estimate.yul.zbin", "sourceCodePath": "bootloader/build/fee_estimate.yul", - "bytecodeHash": "0x0100094fe95a0ee1b8b9a86befeb23939f5036a69a5808235e058e1af1e935d8", - "sourceCodeHash": "0x6071a22c177ad6ed84a6d8a283eb3272dbb127da394417c11fb94056dfcce3cc" + "bytecodeHash": "0x0100094732ff180996ee3f6f01d7ca5ac5eac9117b1e30ec2e106a9640c8f341", + "sourceCodeHash": "0xd9d968237e1e9afc6d7ba5e330d60cdf146fc8493b1c4a5f4150d8a67e9f335f" }, { "contractName": "gas_test", "bytecodePath": "bootloader/build/artifacts/gas_test.yul.zbin", "sourceCodePath": "bootloader/build/gas_test.yul", - "bytecodeHash": "0x010008d5319bd1a8c92f7519824ca73c6b993930a68982b205ad9cce2b50e147", - "sourceCodeHash": "0x0d08c8894d54a6498ae0ffbc10816439652c1b43022a77364b9aa4df91cd3ba5" + "bytecodeHash": "0x010008cd6f786da6cf3b34ce5e6bf922eaafe396a841468ed79c322dc801d7a9", + "sourceCodeHash": "0xc59e6ba244be9ce1c26bc8116b67c455e7bea36472328774f0029d3dc4cd6c7e" }, { "contractName": "playground_batch", "bytecodePath": "bootloader/build/artifacts/playground_batch.yul.zbin", "sourceCodePath": "bootloader/build/playground_batch.yul", - "bytecodeHash": "0x0100095541c24966c34984d5521cb7a06263eb4715205f5632a6d5f596010c24", - "sourceCodeHash": "0x5a8ba82172223403a83ec95be070c87ec9bf931898f4df2091c93535fefd8223" + "bytecodeHash": "0x0100094d9abae69cf77aac12eb0dd4fd398d89c5643d2077590e7c648424458a", + "sourceCodeHash": "0x632ee7af84537c69edf5471611fb7302323a143c6e816a29e0b5fdfac29847f9" }, { "contractName": "proved_batch", "bytecodePath": "bootloader/build/artifacts/proved_batch.yul.zbin", "sourceCodePath": "bootloader/build/proved_batch.yul", - "bytecodeHash": "0x010008e50a84cb5e11b650d08b8040a90cd42203490f09362e5e39f1925234aa", - "sourceCodeHash": "0x2c4178f33c0c8ac6402d0f9f53c01c3a143c4d789cf97ba491ae590c4515a2b0" + "bytecodeHash": "0x010008dd31cb425e7e1da1b52c907499af44a35b429a4c92067b028cd81df106", + "sourceCodeHash": "0x3b5d1ae48b9944e100852062274d4940389f9c1de8e57241f8d381caa49df3c1" } ] From 1d361926beeb7f776d7e685286482e980ccff210 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 27 Aug 2024 15:49:28 -0300 Subject: [PATCH 35/59] Remove download compiler step since old hardhat version already does it --- system-contracts/scripts/utils.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/system-contracts/scripts/utils.ts b/system-contracts/scripts/utils.ts index b8188c0e4..e06c14e50 100644 --- a/system-contracts/scripts/utils.ts +++ b/system-contracts/scripts/utils.ts @@ -207,15 +207,6 @@ export async function getSolcLocation(): Promise { const solcVersion = hre.config.solidity.compilers[0].version; - if (!(await downloader.isCompilerDownloaded(solcVersion))) { - console.log(`Compiler ${solcVersion} not found, downloading...`); - await downloader.downloadCompiler( - solcVersion, - async () => {}, - async () => {} - ); - } - return (await downloader.getCompiler(solcVersion))!.compilerPath; } From 5774d9ebbdffbc7d5d7714b66f938be57049630f Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 27 Aug 2024 15:49:40 -0300 Subject: [PATCH 36/59] Update system contract hashes --- system-contracts/SystemContractsHashes.json | 54 ++++++++++----------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 886b0b594..d6f552046 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,119 +3,119 @@ "contractName": "AccountCodeStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x01000083d2aea30622e239d77e7af69e459f3e54a25d80f4bfcac94eebb92f35", + "bytecodeHash": "0x01000083f5c41c79561ef0eb3901e87e437aa97d6ff1e9148cf88bdcb3d79983", "sourceCodeHash": "0xd093d1595f6395c3d447c86e377d847690bcbd6b0e69488b4161286bf9e4ea82" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010007e984aa274015d900d32e01f5ae34c346bb303cbcea5328fda4050bb328", + "bytecodeHash": "0x010007df5e1added77f71992b3523c8f41d0fae2d21a0144df70a8b19cbd73bb", "sourceCodeHash": "0x8462a9ddedbff81c6cf8fc3ac33500f4f416fc31b1f025d90bb760fa4ebca8a4" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004deec68816dc8f01d94db0a6eb2d9623297a85767652db2aa3c9e3d363", + "bytecodeHash": "0x0100004d3638948aa9391f1fec3e9dd6127531003496636506e9dd1d348475c6", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x010001534b9733c31d514e5c3a0017f86ff030a9bdbf3611e808c16072aaffc2", + "bytecodeHash": "0x0100014fa5280d9df8df0b95b5d773771f90238c56fa7d107149b8b45053bb9e", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010007534a7f55eee49ea99820c45d4e484a3192591e6613c87292565cfa8d41", + "bytecodeHash": "0x01000735a9539fdea7945d9993813db2ddaf18b7cfaa31d9591a128c1caf18ad", "sourceCodeHash": "0x3d6200608d8ee9ecd71f6d44f6e30197b0643374e225894c30f0b00d83e71bfb" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x01000057d0c12542ad9656d6581f114bbf2ef9f7681119eaeb601895776d552e", + "bytecodeHash": "0x01000049bba25ccf15dce4a4919e5bc6d26d2bab101ec8fec698316f10765e9c", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x010005ab0c1bd9cb04aaec180331f6eec79354413e5cfff9cf2076fdbb4b965b", + "bytecodeHash": "0x0100058d1815df17a4900aeb68db2445d025cf41acc67795bf32582e60d7a92a", "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { "contractName": "EmptyContract", "bytecodePath": "artifacts-zk/contracts-preprocessed/EmptyContract.sol/EmptyContract.json", "sourceCodePath": "contracts-preprocessed/EmptyContract.sol", - "bytecodeHash": "0x01000007bad04be2f33020fe006812a44718c6de4545c3357645b65debf6a18e", + "bytecodeHash": "0x010000078f32964c38fbd138a0369f4723f07ac6f4919c45ef738c18bf874ccd", "sourceCodeHash": "0xcac36c5afafbcff83601f4fbfdff660aa66d8c80ed97b9322d3011c1926b554d" }, { "contractName": "EvmGasManager", "bytecodePath": "artifacts-zk/contracts-preprocessed/EvmGasManager.sol/EvmGasManager.json", "sourceCodePath": "contracts-preprocessed/EvmGasManager.sol", - "bytecodeHash": "0x010000ed0e7701f0ee1ab3e7f19096b6306321b92d9e1ddb63573450cf18d6b4", + "bytecodeHash": "0x010000ed59ae506984e6d98e8e05afce8b2cdc336f1b8b179d4a72bb799375ac", "sourceCodeHash": "0x6e58be3f630adf305473e9a1844a448d9836322c10dc79e953a7ae319fc009b0" }, { "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000039086bd8d011cdbee75bd5d8f353a068ac6d225d9660de7bebb86ec4e2", + "bytecodeHash": "0x0100003998de054dfdabd41ecf2ad6f28463a94829f2c9aca382226ec50c6b5a", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cf9307e59e12fd3fb768da1783e89af637230ef50fd2eea7da3226ce01", + "bytecodeHash": "0x010000cf101e7f2d96b05f1f797c99de80271eb8c20e62ecf4311f24684cc20b", "sourceCodeHash": "0xe07e6543ac09b86042eff5f9067df6db10a4fc039ecb56098a882ee1019c3031" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010002b1f8226eca1512e5be51f4515b4b2122ef644db81391c556aea0813cb8", + "bytecodeHash": "0x01000299392a253d20178749eaa3ab9098b97ff7a7f1aff3a1ea89c4728d9315", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x01000103333b0ca5b07895fff7974937705497f524588ce6d475aef277da1481", + "bytecodeHash": "0x01000103e5cf0eab5df70d128f9310c40519e5e0209ad9570133640b84509e40", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x01000065d3f346bcd121e9b6ad7f883cb5cbfa982a0966fc24e318acb5d79c7e", + "bytecodeHash": "0x0100005d1283cf6be4658b5ac84c33d1ab86a60df646b8e57d578c61a438b4d0", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010001017915583cf42a949b1decaf1ef9df356f66a501b9a988cdff9d951bf6", + "bytecodeHash": "0x010000fb1ae585d33ac95fc980136cfff6245226fe2b98713c9092152c3b32c8", "sourceCodeHash": "0x9ec18b6a78758b999f9acdca50b1f2464beac1cb317b7184017fd4e96ad7ec58" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x0100004796b09e7f678de61de92079e0daeb0403d3dc70e34a7c688a63010af5", + "bytecodeHash": "0x01000047046412295a727492d622b3ee861e577808994f5f06e2074e12ad12ca", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001ab2bab377b8c6f95801ca4ba783d549f8345712c1bc3bab84b967c79df", + "bytecodeHash": "0x010001a5795c254a344b41852ca07da7dad3498865bb977c6982d6b79c65cfc9", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { @@ -192,35 +192,35 @@ "contractName": "bootloader_test", "bytecodePath": "bootloader/build/artifacts/bootloader_test.yul.zbin", "sourceCodePath": "bootloader/build/bootloader_test.yul", - "bytecodeHash": "0x010003cbe27a00667d83135f1db1dba76ca9d36b58125d38bd6b4182f7e4f938", - "sourceCodeHash": "0x193eee1c508be6af17148506bc010fbb72ed465fa072f0458232e602727ea6b1" + "bytecodeHash": "0x010003cbad30bb6543be2f40f546f8d4ad1144944b752fd413fbd312b3402758", + "sourceCodeHash": "0xc6858d3e727721ad33a8264363bb63171cc29b11c2c5b85b26bfd586b3bcf5dd" }, { "contractName": "fee_estimate", "bytecodePath": "bootloader/build/artifacts/fee_estimate.yul.zbin", "sourceCodePath": "bootloader/build/fee_estimate.yul", - "bytecodeHash": "0x0100094732ff180996ee3f6f01d7ca5ac5eac9117b1e30ec2e106a9640c8f341", - "sourceCodeHash": "0xd9d968237e1e9afc6d7ba5e330d60cdf146fc8493b1c4a5f4150d8a67e9f335f" + "bytecodeHash": "0x0100094725bd63e88a52a4ed152deb592984b35e91e0de8dc3decf604956c20d", + "sourceCodeHash": "0xe745a8ff3a83338f714a38f3f121acda7ca775803f5588fa585d151c0e2cda59" }, { "contractName": "gas_test", "bytecodePath": "bootloader/build/artifacts/gas_test.yul.zbin", "sourceCodePath": "bootloader/build/gas_test.yul", - "bytecodeHash": "0x010008cd6f786da6cf3b34ce5e6bf922eaafe396a841468ed79c322dc801d7a9", - "sourceCodeHash": "0xc59e6ba244be9ce1c26bc8116b67c455e7bea36472328774f0029d3dc4cd6c7e" + "bytecodeHash": "0x010008cd0f1080aa347d6f856e06f59ce64a23b64dce9e023dcc9dff153bacd0", + "sourceCodeHash": "0xbb05b728cd5d1d0dd7c66d5bbaa2c63e1b4eb85e626aedc9efc72dca275b7042" }, { "contractName": "playground_batch", "bytecodePath": "bootloader/build/artifacts/playground_batch.yul.zbin", "sourceCodePath": "bootloader/build/playground_batch.yul", - "bytecodeHash": "0x0100094d9abae69cf77aac12eb0dd4fd398d89c5643d2077590e7c648424458a", - "sourceCodeHash": "0x632ee7af84537c69edf5471611fb7302323a143c6e816a29e0b5fdfac29847f9" + "bytecodeHash": "0x0100094d271fcdb4bb08181bafdffa4b17e2b5629f067c8ba82264e8e99814b1", + "sourceCodeHash": "0xb27c8e2990513fd97b4d3badf9e9b9dd7a58acc94f37b1084e4d4b5f16c1efbe" }, { "contractName": "proved_batch", "bytecodePath": "bootloader/build/artifacts/proved_batch.yul.zbin", "sourceCodePath": "bootloader/build/proved_batch.yul", - "bytecodeHash": "0x010008dd31cb425e7e1da1b52c907499af44a35b429a4c92067b028cd81df106", - "sourceCodeHash": "0x3b5d1ae48b9944e100852062274d4940389f9c1de8e57241f8d381caa49df3c1" + "bytecodeHash": "0x010008ddf6824c3f8778b86a85d568ddfb45c29bf23b604fad20b91e6d8d458b", + "sourceCodeHash": "0xa2e4196dc32d0a911ee45ff3ccd2479735bd78eeef55a73ad5fb956838d440fa" } ] From 4d15c5ef8e7fb7f46223c0755c0647d9e362565a Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 27 Aug 2024 15:50:02 -0300 Subject: [PATCH 37/59] Get the original lock file from dev to mantain correct versions --- yarn.lock | 1082 +++++++++++++++++++++++++++++------------------------ 1 file changed, 597 insertions(+), 485 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1de54180b..2dfdc5f28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,24 +3,24 @@ "@babel/code-frame@^7.0.0": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" - integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + version "7.24.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" + integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== dependencies: - "@babel/highlight" "^7.24.7" + "@babel/highlight" "^7.24.2" picocolors "^1.0.0" -"@babel/helper-validator-identifier@^7.24.7": +"@babel/helper-validator-identifier@^7.22.20": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== -"@babel/highlight@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" - integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== +"@babel/highlight@^7.24.2": + version "7.24.2" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26" + integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== dependencies: - "@babel/helper-validator-identifier" "^7.24.7" + "@babel/helper-validator-identifier" "^7.22.20" chalk "^2.4.2" js-tokens "^4.0.0" picocolors "^1.0.0" @@ -63,9 +63,9 @@ eslint-visitor-keys "^3.3.0" "@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" - integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== "@eslint/eslintrc@^2.1.4": version "2.1.4" @@ -662,9 +662,9 @@ integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== "@jridgewell/sourcemap-codec@^1.4.10": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -755,22 +755,22 @@ chalk "4.1.2" dockerode "^3.3.4" -"@matterlabs/hardhat-zksync-solc@^1.0.5", "@matterlabs/hardhat-zksync-solc@^1.1.4", "@matterlabs/hardhat-zksync-solc@^1.2.1": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-1.2.3.tgz#90fff87e36f3bf39e594686d8959111e40a5fff3" - integrity sha512-vRvA89DEV49vBcm1/lZVVp+k3OHjuFzhGnzzgwk9zmV9rr4onRDtTShPbu7fP6MdJOTZQ0F3f82rYKsh0ERqNA== +"@matterlabs/hardhat-zksync-solc@^1.0.5", "@matterlabs/hardhat-zksync-solc@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-1.1.4.tgz#04a2fad6fb6b6944c64ad969080ee65b9af3f617" + integrity sha512-4/usbogh9neewR2/v8Dn2OzqVblZMUuT/iH2MyPZgPRZYQlL4SlZtMvokU9UQjZT6iSoaKCbbdWESHDHSzfUjA== dependencies: - "@nomiclabs/hardhat-docker" "^2.0.2" - chai "^4.3.4" - chalk "^4.1.2" - debug "^4.3.5" + "@nomiclabs/hardhat-docker" "^2.0.0" + chai "^4.3.6" + chalk "4.1.2" + debug "^4.3.4" dockerode "^4.0.2" - fs-extra "^11.2.0" + fs-extra "^11.1.1" proper-lockfile "^4.1.2" - semver "^7.6.2" - sinon "^18.0.0" + semver "^7.5.1" + sinon "^17.0.1" sinon-chai "^3.7.0" - undici "^6.18.2" + undici "^5.14.0" "@matterlabs/hardhat-zksync-verify@0.6.1": version "0.6.1" @@ -805,21 +805,22 @@ zksync-ethers "^5.0.0" "@matterlabs/hardhat-zksync-verify@^1.4.3": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-verify/-/hardhat-zksync-verify-1.6.0.tgz#701ea2812c3a554bcc72e04e23a4af4b2ad0709c" - integrity sha512-RsWlQbI23BDXMsxTtvHXpzx1dBotI2p2trvdG+r1uN/KAmMJBOKIqxce2UNXl8skd5Gtysa4GPjXEp4yaf2KrA== + version "1.4.3" + resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-verify/-/hardhat-zksync-verify-1.4.3.tgz#fc36d2ea385eab553ce0b3c3fbc9e216c607873f" + integrity sha512-TONID/+mG8KngZ9iI8yiOgC8VD+cus7M+ejCjF4bGNzsmmzsklGJwzry6bQpk8BXqzsMgbuV+4KjDT4JXiS/QA== dependencies: - "@ethersproject/abi" "^5.7.0" + "@ethersproject/abi" "^5.1.2" "@ethersproject/address" "5.7.0" - "@matterlabs/hardhat-zksync-solc" "^1.2.1" - "@nomicfoundation/hardhat-verify" "^2.0.8" - axios "^1.7.2" - cbor "^9.0.2" - chai "^4.3.4" - chalk "^4.1.2" - debug "^4.3.5" - semver "^7.6.2" - sinon "^18.0.0" + "@matterlabs/hardhat-zksync-solc" "^1.1.4" + "@nomicfoundation/hardhat-verify" "^2.0.0" + "@openzeppelin/contracts" "^4.9.2" + axios "^1.6.2" + cbor "^8.1.0" + chai "^4.3.6" + chalk "4.1.2" + debug "^4.1.1" + hardhat "^2.19.4" + sinon "^17.0.1" sinon-chai "^3.7.0" "@matterlabs/prettier-config@^1.0.3": @@ -843,19 +844,24 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" -"@noble/curves@1.4.2", "@noble/curves@~1.4.0": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" - integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== +"@noble/curves@1.3.0", "@noble/curves@~1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e" + integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA== dependencies: - "@noble/hashes" "1.4.0" + "@noble/hashes" "1.3.3" "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== -"@noble/hashes@1.4.0", "@noble/hashes@^1.4.0", "@noble/hashes@~1.4.0": +"@noble/hashes@1.3.3", "@noble/hashes@~1.3.2": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" + integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== + +"@noble/hashes@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== @@ -886,75 +892,105 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nolyfill/is-core-module@1.0.39": - version "1.0.39" - resolved "https://registry.yarnpkg.com/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz#3dc35ba0f1e66b403c00b39344f870298ebb1c8e" - integrity sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA== +"@nomicfoundation/edr-darwin-arm64@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.7.tgz#c204edc79643624dbd431b489b254778817d8244" + integrity sha512-6tK9Lv/lSfyBvpEQ4nsTfgxyDT1y1Uv/x8Wa+aB+E8qGo3ToexQ1BMVjxJk6PChXCDOWxB3B4KhqaZFjdhl3Ow== -"@nomicfoundation/edr-darwin-arm64@0.3.8": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.8.tgz#09de1f03c0336670fce959f376f0fe9137545836" - integrity sha512-eB0leCexS8sQEmfyD72cdvLj9djkBzQGP4wSQw6SNf2I4Sw4Cnzb3d45caG2FqFFjbvfqL0t+badUUIceqQuMw== +"@nomicfoundation/edr-darwin-arm64@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.4.0.tgz#bbb43f0e01f40839b0bd38c2c443cb6910ae955f" + integrity sha512-7+rraFk9tCqvfemv9Ita5vTlSBAeO/S5aDKOgGRgYt0JEKZlrX161nDW6UfzMPxWl9GOLEDUzCEaYuNmXseUlg== "@nomicfoundation/edr-darwin-arm64@0.5.2": version "0.5.2" resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.5.2.tgz#72f7a826c9f0f2c91308edca562de3b9484ac079" integrity sha512-Gm4wOPKhbDjGTIRyFA2QUAPfCXA1AHxYOKt3yLSGJkQkdy9a5WW+qtqKeEKHc/+4wpJSLtsGQfpzyIzggFfo/A== -"@nomicfoundation/edr-darwin-x64@0.3.8": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.8.tgz#c3ca237c74ed3b6fb800fd7f1de7174f4ad24f72" - integrity sha512-JksVCS1N5ClwVF14EvO25HCQ+Laljh/KRfHERMVAC9ZwPbTuAd/9BtKvToCBi29uCHWqsXMI4lxCApYQv2nznw== +"@nomicfoundation/edr-darwin-x64@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.7.tgz#c3b394445084270cc5250d6c1869b0574e7ef810" + integrity sha512-1RrQ/1JPwxrYO69e0tglFv5H+ggour5Ii3bb727+yBpBShrxtOTQ7fZyfxA5h62LCN+0Z9wYOPeQ7XFcVurMaQ== + +"@nomicfoundation/edr-darwin-x64@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.4.0.tgz#b1ffcd9142418fd8498de34a7336b3f977907c86" + integrity sha512-+Hrc0mP9L6vhICJSfyGo/2taOToy1AIzVZawO3lU8Lf7oDQXfhQ4UkZnkWAs9SVu1eUwHUGGGE0qB8644piYgg== "@nomicfoundation/edr-darwin-x64@0.5.2": version "0.5.2" resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.5.2.tgz#6d0fedb219d664631c6feddc596ab8c3bbc36fa8" integrity sha512-ClyABq2dFCsrYEED3/UIO0c7p4H1/4vvlswFlqUyBpOkJccr75qIYvahOSJRM62WgUFRhbSS0OJXFRwc/PwmVg== -"@nomicfoundation/edr-linux-arm64-gnu@0.3.8": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.8.tgz#08bd367789e745f4e78a8a87368fc470eea8a7de" - integrity sha512-raCE+fOeNXhVBLUo87cgsHSGvYYRB6arih4eG6B9KGACWK5Veebtm9xtKeiD8YCsdUlUfat6F7ibpeNm91fpsA== +"@nomicfoundation/edr-linux-arm64-gnu@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.7.tgz#6d65545a44d1323bb7ab08c3306947165d2071de" + integrity sha512-ds/CKlBoVXIihjhflhgPn13EdKWed6r5bgvMs/YwRqT5wldQAQJZWAfA2+nYm0Yi2gMGh1RUpBcfkyl4pq7G+g== + +"@nomicfoundation/edr-linux-arm64-gnu@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.4.0.tgz#8173d16d4f6f2b3e82ba7096d2a1ea3619d8bfa7" + integrity sha512-4HUDMchNClQrVRfVTqBeSX92hM/3khCgpZkXP52qrnJPqgbdCxosOehlQYZ65wu0b/kaaZSyvACgvCLSQ5oSzQ== "@nomicfoundation/edr-linux-arm64-gnu@0.5.2": version "0.5.2" resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.5.2.tgz#60e4d52d963141bc2bb4a02639dc590a7fbdda2f" integrity sha512-HWMTVk1iOabfvU2RvrKLDgtFjJZTC42CpHiw2h6rfpsgRqMahvIlx2jdjWYzFNy1jZKPTN1AStQ/91MRrg5KnA== -"@nomicfoundation/edr-linux-arm64-musl@0.3.8": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.8.tgz#9cab5cbec0052cb5812c6c66c463d28a756cd916" - integrity sha512-PwiDp4wBZWMCIy29eKkv8moTKRrpiSDlrc+GQMSZLhOAm8T33JKKXPwD/2EbplbhCygJDGXZdtEKl9x9PaH66A== +"@nomicfoundation/edr-linux-arm64-musl@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.7.tgz#5368534bceac1a8c18b1be6b908caca5d39b0c03" + integrity sha512-e29udiRaPujhLkM3+R6ju7QISrcyOqpcaxb2FsDWBkuD7H8uU9JPZEyyUIpEp5uIY0Jh1eEJPKZKIXQmQAEAuw== + +"@nomicfoundation/edr-linux-arm64-musl@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.4.0.tgz#b1ce293a7c3e0d9f70391e1aef1a82b83b997567" + integrity sha512-D4J935ZRL8xfnP3zIFlCI9jXInJ0loDUkCTLeCEbOf2uuDumWDghKNQlF1itUS+EHaR1pFVBbuwqq8hVK0dASg== "@nomicfoundation/edr-linux-arm64-musl@0.5.2": version "0.5.2" resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.5.2.tgz#6676a09eab57c435a16ffc144658c896acca9baa" integrity sha512-CwsQ10xFx/QAD5y3/g5alm9+jFVuhc7uYMhrZAu9UVF+KtVjeCvafj0PaVsZ8qyijjqVuVsJ8hD1x5ob7SMcGg== -"@nomicfoundation/edr-linux-x64-gnu@0.3.8": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.8.tgz#d4a11b6ebcd1b29d7431d185c6df3e65a2cd4bde" - integrity sha512-6AcvA/XKoipGap5jJmQ9Y6yT7Uf39D9lu2hBcDCXnXbMcXaDGw4mn1/L4R63D+9VGZyu1PqlcJixCUZlGGIWlg== +"@nomicfoundation/edr-linux-x64-gnu@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.7.tgz#42349bf5941dbb54a5719942924c6e4e8cde348e" + integrity sha512-/xkjmTyv+bbJ4akBCW0qzFKxPOV4AqLOmqurov+s9umHb16oOv72osSa3SdzJED2gHDaKmpMITT4crxbar4Axg== + +"@nomicfoundation/edr-linux-x64-gnu@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.4.0.tgz#4c12c4e4bfd3d837f5663ad7cbf7cb6d5634ef83" + integrity sha512-6x7HPy+uN5Cb9N77e2XMmT6+QSJ+7mRbHnhkGJ8jm4cZvWuj2Io7npOaeHQ3YHK+TiQpTnlbkjoOIpEwpY3XZA== "@nomicfoundation/edr-linux-x64-gnu@0.5.2": version "0.5.2" resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.5.2.tgz#f558d9697ce961410e7a7468f9ab8c8a601b9df6" integrity sha512-CWVCEdhWJ3fmUpzWHCRnC0/VLBDbqtqTGTR6yyY1Ep3S3BOrHEAvt7h5gx85r2vLcztisu2vlDq51auie4IU1A== -"@nomicfoundation/edr-linux-x64-musl@0.3.8": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.8.tgz#b8eef960d06380a365866ddd1e97ecb7fbf6bd70" - integrity sha512-cxb0sEmZjlwhYWO28sPsV64VDx31ekskhC1IsDXU1p9ntjHSJRmW4KEIqJ2O3QwJap/kLKfMS6TckvY10gjc6w== +"@nomicfoundation/edr-linux-x64-musl@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.7.tgz#e6babe11c9a8012f1284e6e48c3551861f2a7cd4" + integrity sha512-QwBP9xlmsbf/ldZDGLcE4QiAb8Zt46E/+WLpxHBATFhGa7MrpJh6Zse+h2VlrT/SYLPbh2cpHgSmoSlqVxWG9g== + +"@nomicfoundation/edr-linux-x64-musl@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.4.0.tgz#8842004aa1a47c504f10863687da28b65dca7baa" + integrity sha512-3HFIJSXgyubOiaN4MWGXx2xhTnhwlJk0PiSYNf9+L/fjBtcRkb2nM910ZJHTvqCb6OT98cUnaKuAYdXIW2amgw== "@nomicfoundation/edr-linux-x64-musl@0.5.2": version "0.5.2" resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.5.2.tgz#c9c9cbb2997499f75c1d022be724b0551d44569f" integrity sha512-+aJDfwhkddy2pP5u1ISg3IZVAm0dO836tRlDTFWtvvSMQ5hRGqPcWwlsbobhDQsIxhPJyT7phL0orCg5W3WMeA== -"@nomicfoundation/edr-win32-x64-msvc@0.3.8": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.8.tgz#ac7061aeb07cc847c429513080b76bb05297a869" - integrity sha512-yVuVPqRRNLZk7TbBMkKw7lzCvI8XO8fNTPTYxymGadjr9rEGRuNTU1yBXjfJ59I1jJU/X2TSkRk1OFX0P5tpZQ== +"@nomicfoundation/edr-win32-x64-msvc@0.3.7": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.7.tgz#1504b98f305f03be153b0220a546985660de9dc6" + integrity sha512-j/80DEnkxrF2ewdbk/gQ2EOPvgF0XSsg8D0o4+6cKhUVAW6XwtWKzIphNL6dyD2YaWEPgIrNvqiJK/aln0ww4Q== + +"@nomicfoundation/edr-win32-x64-msvc@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.4.0.tgz#29d8bbb2edf9912a95f5453855cf17cdcb269957" + integrity sha512-CP4GsllEfXEz+lidcGYxKe5rDJ60TM5/blB5z/04ELVvw6/CK9eLcYeku7HV0jvV7VE6dADYKSdQyUkvd0El+A== "@nomicfoundation/edr-win32-x64-msvc@0.5.2": version "0.5.2" @@ -962,19 +998,32 @@ integrity sha512-CcvvuA3sAv7liFNPsIR/68YlH6rrybKzYttLlMr80d4GKJjwJ5OKb3YgE6FdZZnOfP19HEHhsLcE0DPLtY3r0w== "@nomicfoundation/edr@^0.3.1": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.3.8.tgz#28fe7ae4f462ae74a16cd1a714ff7b1cd9c22b4c" - integrity sha512-u2UJ5QpznSHVkZRh6ePWoeVb6kmPrrqh08gCnZ9FHlJV9CITqlrTQHJkacd+INH31jx88pTAJnxePE4XAiH5qg== - dependencies: - "@nomicfoundation/edr-darwin-arm64" "0.3.8" - "@nomicfoundation/edr-darwin-x64" "0.3.8" - "@nomicfoundation/edr-linux-arm64-gnu" "0.3.8" - "@nomicfoundation/edr-linux-arm64-musl" "0.3.8" - "@nomicfoundation/edr-linux-x64-gnu" "0.3.8" - "@nomicfoundation/edr-linux-x64-musl" "0.3.8" - "@nomicfoundation/edr-win32-x64-msvc" "0.3.8" - -"@nomicfoundation/edr@^0.5.2": + version "0.3.7" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.3.7.tgz#9c75edf1fcf601617905b2c89acf103f4786d017" + integrity sha512-v2JFWnFKRsnOa6PDUrD+sr8amcdhxnG/YbL7LzmgRGU1odWEyOF4/EwNeUajQr4ZNKVWrYnJ6XjydXtUge5OBQ== + optionalDependencies: + "@nomicfoundation/edr-darwin-arm64" "0.3.7" + "@nomicfoundation/edr-darwin-x64" "0.3.7" + "@nomicfoundation/edr-linux-arm64-gnu" "0.3.7" + "@nomicfoundation/edr-linux-arm64-musl" "0.3.7" + "@nomicfoundation/edr-linux-x64-gnu" "0.3.7" + "@nomicfoundation/edr-linux-x64-musl" "0.3.7" + "@nomicfoundation/edr-win32-x64-msvc" "0.3.7" + +"@nomicfoundation/edr@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.4.0.tgz#4895ecb6ef321136db837458949c37cce4a29459" + integrity sha512-T96DMSogO8TCdbKKctvxfsDljbhFOUKWc9fHJhSeUh71EEho2qR4951LKQF7t7UWEzguVYh/idQr5L/E3QeaMw== + dependencies: + "@nomicfoundation/edr-darwin-arm64" "0.4.0" + "@nomicfoundation/edr-darwin-x64" "0.4.0" + "@nomicfoundation/edr-linux-arm64-gnu" "0.4.0" + "@nomicfoundation/edr-linux-arm64-musl" "0.4.0" + "@nomicfoundation/edr-linux-x64-gnu" "0.4.0" + "@nomicfoundation/edr-linux-x64-musl" "0.4.0" + "@nomicfoundation/edr-win32-x64-msvc" "0.4.0" + +"@nomicfoundation/edr@^0.5.0": version "0.5.2" resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.5.2.tgz#e8c7b3d3dd4a312432ab3930dec60f76dc5c4926" integrity sha512-hW/iLvUQZNTVjFyX/I40rtKvvDOqUEyIi96T28YaLfmPL+3LW2lxmYLUXEJ6MI14HzqxDqrLyhf6IbjAa2r3Dw== @@ -1029,9 +1078,9 @@ ordinal "^1.0.3" "@nomicfoundation/hardhat-ethers@^3.0.4": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.7.tgz#be90f79e96a22e6e982bca20ab0af05ed1f09c26" - integrity sha512-pxLWpDiqC208shoz/lMbVFbxcVxE+qIs8qDrwdcubWH99UO1p6uwXakMa36ICRfB/IEToSLDJGSsKhwY84feCQ== + version "3.0.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.5.tgz#0422c2123dec7c42e7fb2be8e1691f1d9708db56" + integrity sha512-RNFe8OtbZK6Ila9kIlHp0+S80/0Bu/3p41HUpaRIoHLm6X3WekTd83vob3rE54Duufu1edCiBDxspBzi2rxHHw== dependencies: debug "^4.1.1" lodash.isequal "^4.5.0" @@ -1051,10 +1100,10 @@ table "^6.8.0" undici "^5.14.0" -"@nomicfoundation/hardhat-verify@^2.0.0", "@nomicfoundation/hardhat-verify@^2.0.8": - version "2.0.9" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.9.tgz#98a1c9a3742b008be71a709d074f10dec23bc5f0" - integrity sha512-7kD8hu1+zlnX87gC+UN4S0HTKBnIsDfXZ/pproq1gYsK94hgCk+exvzXbwR0X2giiY/RZPkqY9oKRi0Uev91hQ== +"@nomicfoundation/hardhat-verify@^2.0.0": + version "2.0.8" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.8.tgz#6a77dc03de990a1a3aa8e6dc073c393263dbf258" + integrity sha512-x/OYya7A2Kcz+3W/J78dyDHxr0ezU23DKTrRKfy5wDPCnePqnr79vm8EXqX3gYps6IjPBYyGPZ9K6E5BnrWx5Q== dependencies: "@ethersproject/abi" "^5.1.2" "@ethersproject/address" "^5.0.2" @@ -1066,55 +1115,73 @@ table "^6.8.0" undici "^5.14.0" -"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz#3a9c3b20d51360b20affb8f753e756d553d49557" - integrity sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw== +"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz#4c858096b1c17fe58a474fe81b46815f93645c15" + integrity sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w== -"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz#74dcfabeb4ca373d95bd0d13692f44fcef133c28" - integrity sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw== +"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.1.tgz#6e25ccdf6e2d22389c35553b64fe6f3fdaec432c" + integrity sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA== -"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz#4af5849a89e5a8f511acc04f28eb5d4460ba2b6a" - integrity sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA== +"@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.1.tgz#0a224ea50317139caeebcdedd435c28a039d169c" + integrity sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA== -"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz#54036808a9a327b2ff84446c130a6687ee702a8e" - integrity sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA== +"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.1.tgz#dfa085d9ffab9efb2e7b383aed3f557f7687ac2b" + integrity sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg== -"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz#466cda0d6e43691986c944b909fc6dbb8cfc594e" - integrity sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g== +"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.1.tgz#c9e06b5d513dd3ab02a7ac069c160051675889a4" + integrity sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w== -"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz#2b35826987a6e94444140ac92310baa088ee7f94" - integrity sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg== +"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.1.tgz#8d328d16839e52571f72f2998c81e46bf320f893" + integrity sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA== -"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz#e6363d13b8709ca66f330562337dbc01ce8bbbd9" - integrity sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA== +"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.1.tgz#9b49d0634b5976bb5ed1604a1e1b736f390959bb" + integrity sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w== + +"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.1.tgz#e2867af7264ebbcc3131ef837878955dd6a3676f" + integrity sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg== + +"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.1.tgz#0685f78608dd516c8cdfb4896ed451317e559585" + integrity sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ== + +"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.1.tgz#c9a44f7108646f083b82e851486e0f6aeb785836" + integrity sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw== "@nomicfoundation/solidity-analyzer@^0.1.0": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz#8bcea7d300157bf3a770a851d9f5c5e2db34ac55" - integrity sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA== + version "0.1.1" + resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz#f5f4d36d3f66752f59a57e7208cd856f3ddf6f2d" + integrity sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg== optionalDependencies: - "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.2" - "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.2" - "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.2" - "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.2" - -"@nomiclabs/hardhat-docker@^2.0.0", "@nomiclabs/hardhat-docker@^2.0.2": + "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.1" + "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.1" + "@nomicfoundation/solidity-analyzer-freebsd-x64" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.1" + "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.1" + "@nomicfoundation/solidity-analyzer-win32-arm64-msvc" "0.1.1" + "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.1" + "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.1" + +"@nomiclabs/hardhat-docker@^2.0.0": version "2.0.2" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-docker/-/hardhat-docker-2.0.2.tgz#ae964be17951275a55859ff7358e9e7c77448846" integrity sha512-XgGEpRT3wlA1VslyB57zyAHV+oll8KnV1TjwnxxC1tpAL04/lbdwpdO5KxInVN8irMSepqFpsiSkqlcnvbE7Ng== @@ -1182,9 +1249,9 @@ graceful-fs "4.2.10" "@pnpm/npm-conf@^2.1.0": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz#bb375a571a0bd63ab0a23bece33033c683e9b6b0" - integrity sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw== + version "2.2.2" + resolved "https://registry.yarnpkg.com/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz#0058baf1c26cbb63a828f0193795401684ac86f0" + integrity sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA== dependencies: "@pnpm/config.env-replace" "^1.1.0" "@pnpm/network.ca-file" "^1.0.1" @@ -1227,10 +1294,10 @@ path-browserify "^1.0.0" url "^0.11.0" -"@scure/base@~1.1.0", "@scure/base@~1.1.6": - version "1.1.7" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.7.tgz#fe973311a5c6267846aa131bc72e96c5d40d2b30" - integrity sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g== +"@scure/base@~1.1.0", "@scure/base@~1.1.4": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.6.tgz#8ce5d304b436e4c84f896e0550c83e4d88cb917d" + integrity sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g== "@scure/bip32@1.1.5": version "1.1.5" @@ -1241,14 +1308,14 @@ "@noble/secp256k1" "~1.7.0" "@scure/base" "~1.1.0" -"@scure/bip32@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" - integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== +"@scure/bip32@1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.3.tgz#a9624991dc8767087c57999a5d79488f48eae6c8" + integrity sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ== dependencies: - "@noble/curves" "~1.4.0" - "@noble/hashes" "~1.4.0" - "@scure/base" "~1.1.6" + "@noble/curves" "~1.3.0" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.4" "@scure/bip39@1.1.1": version "1.1.1" @@ -1258,13 +1325,13 @@ "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" -"@scure/bip39@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" - integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== +"@scure/bip39@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.2.tgz#f3426813f4ced11a47489cbcf7294aa963966527" + integrity sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA== dependencies: - "@noble/hashes" "~1.4.0" - "@scure/base" "~1.1.6" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.4" "@sentry/core@5.30.0": version "5.30.0" @@ -1346,7 +1413,7 @@ dependencies: type-detect "4.0.8" -"@sinonjs/commons@^3.0.0", "@sinonjs/commons@^3.0.1": +"@sinonjs/commons@^3.0.0": version "3.0.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== @@ -1354,11 +1421,11 @@ type-detect "4.0.8" "@sinonjs/fake-timers@^11.2.2": - version "11.3.1" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-11.3.1.tgz#51d6e8d83ca261ff02c0ab0e68e9db23d5cd5999" - integrity sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA== + version "11.2.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz#50063cc3574f4a27bd8453180a04171c85cc9699" + integrity sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw== dependencies: - "@sinonjs/commons" "^3.0.1" + "@sinonjs/commons" "^3.0.0" "@sinonjs/samsam@^8.0.0": version "8.0.0" @@ -1370,9 +1437,9 @@ type-detect "^4.0.8" "@sinonjs/text-encoding@^0.7.2": - version "0.7.3" - resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz#282046f03e886e352b2d5f5da5eb755e01457f3f" - integrity sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA== + version "0.7.2" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" + integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== "@solidity-parser/parser@^0.14.0": version "0.14.5" @@ -1388,6 +1455,11 @@ dependencies: antlr4ts "^0.5.0-alpha.4" +"@solidity-parser/parser@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.17.0.tgz#52a2fcc97ff609f72011014e4c5b485ec52243ef" + integrity sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw== + "@solidity-parser/parser@^0.18.0": version "0.18.0" resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.18.0.tgz#8e77a02a09ecce957255a2f48c9a7178ec191908" @@ -1491,9 +1563,9 @@ "@types/chai" "*" "@types/chai@*", "@types/chai@^4.2.21": - version "4.3.18" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.18.tgz#dd6a46c9796b0435c13f85e8d44c8ea8e37fa2c1" - integrity sha512-2UfJzigyNa8kYTKn7o4hNMPphkxtu4WTJyobK3m4FBpyj7EK5xgtPcOtxLm7Dznk/Qxr0QXn+gQbkg7mCZKdfg== + version "4.3.14" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.14.tgz#ae3055ea2be43c91c9fd700a36d67820026d96e6" + integrity sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w== "@types/concat-stream@^1.6.0": version "1.6.1" @@ -1554,9 +1626,9 @@ "@types/node" "*" "@types/lodash@^4.14.199": - version "4.17.7" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.7.tgz#2f776bcb53adc9e13b2c0dfd493dfcbd7de43612" - integrity sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA== + version "4.17.0" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.0.tgz#d774355e41f372d5350a4d0714abb48194a489c3" + integrity sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA== "@types/lru-cache@5.1.1", "@types/lru-cache@^5.1.0": version "5.1.1" @@ -1589,11 +1661,11 @@ form-data "^4.0.0" "@types/node@*": - version "22.5.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.0.tgz#10f01fe9465166b4cab72e75f60d8b99d019f958" - integrity sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg== + version "20.12.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.6.tgz#72d068870518d7da1d97b49db401e2d6a1805294" + integrity sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ== dependencies: - undici-types "~6.19.2" + undici-types "~5.26.4" "@types/node@11.11.6": version "11.11.6" @@ -1628,9 +1700,9 @@ integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== "@types/qs@^6.2.31": - version "6.9.15" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" - integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== + version "6.9.10" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.10.tgz#0af26845b5067e1c9a622658a51f60a3934d51e8" + integrity sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw== "@types/resolve@^0.0.8": version "0.0.8" @@ -1810,16 +1882,14 @@ acorn-jsx@^5.3.2: integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.1.1: - version "8.3.3" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" - integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== - dependencies: - acorn "^8.11.0" + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== -acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: - version "8.12.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" - integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== +acorn@^8.4.1, acorn@^8.9.0: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== adm-zip@^0.4.16: version "0.4.16" @@ -1857,14 +1927,14 @@ ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.6: uri-js "^4.2.2" ajv@^8.0.1: - version "8.17.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" - integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + version "8.13.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.13.0.tgz#a3939eaec9fb80d217ddf0c3376948c023f28c91" + integrity sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA== dependencies: fast-deep-equal "^3.1.3" - fast-uri "^3.0.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" + uri-js "^4.4.1" amdefine@>=0.0.4: version "1.0.1" @@ -1883,7 +1953,7 @@ ansi-colors@4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== -ansi-colors@^4.1.1, ansi-colors@^4.1.3: +ansi-colors@^4.1.1: version "4.1.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== @@ -1919,10 +1989,15 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -antlr4@^4.11.0, antlr4@^4.13.1-patch-1: - version "4.13.2" - resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.2.tgz#0d084ad0e32620482a9c3a0e2470c02e72e4006d" - integrity sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg== +antlr4@^4.11.0: + version "4.13.1" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.1.tgz#1e0a1830a08faeb86217cb2e6c34716004e4253d" + integrity sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA== + +antlr4@^4.13.1-patch-1: + version "4.13.1-patch-1" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.1-patch-1.tgz#946176f863f890964a050c4f18c47fd6f7e57602" + integrity sha512-OjFLWWLzDMV9rdFhpvroCWR4ooktNg9/nvVYSA5z28wuVpU36QUNuioR1XLnQtcjVlf8npjyz593PxnU/f/Cow== antlr4ts@^0.5.0-alpha.4: version "0.5.0-alpha.4" @@ -2123,9 +2198,9 @@ aws-sign2@~0.7.0: integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.1.tgz#bb5f8b8a20739f6ae1caeaf7eea2c7913df8048e" - integrity sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA== + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== axios@^0.21.1: version "0.21.4" @@ -2134,10 +2209,19 @@ axios@^0.21.1: dependencies: follow-redirects "^1.14.0" -axios@^1.4.0, axios@^1.5.1, axios@^1.6.2, axios@^1.7.2: - version "1.7.5" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.5.tgz#21eed340eb5daf47d29b6e002424b3e88c8c54b1" - integrity sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw== +axios@^1.4.0, axios@^1.5.1: + version "1.6.8" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66" + integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +axios@^1.6.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" @@ -2157,9 +2241,9 @@ balanced-match@^1.0.0: integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base-x@^3.0.2: - version "3.0.10" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.10.tgz#62de58653f8762b5d6f8d9fe30fa75f7b2585a75" - integrity sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ== + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== dependencies: safe-buffer "^5.0.1" @@ -2266,19 +2350,19 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.3, braces@~3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: - fill-range "^7.1.1" + fill-range "^7.0.1" brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== -browser-stdout@1.3.1, browser-stdout@^1.3.1: +browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== @@ -2445,24 +2529,17 @@ cbor@^8.1.0: dependencies: nofilter "^3.1.0" -cbor@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-9.0.2.tgz#536b4f2d544411e70ec2b19a2453f10f83cd9fdb" - integrity sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ== - dependencies: - nofilter "^3.1.0" - chai-as-promised@^7.1.1: - version "7.1.2" - resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.2.tgz#70cd73b74afd519754161386421fb71832c6d041" - integrity sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw== + version "7.1.1" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" + integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== dependencies: check-error "^1.0.2" -chai@^4.3.10, chai@^4.3.4, chai@^4.3.6, chai@^4.3.7: - version "4.5.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8" - integrity sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw== +chai@^4.3.10, chai@^4.3.6, chai@^4.3.7: + version "4.4.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1" + integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g== dependencies: assertion-error "^1.1.0" check-error "^1.0.3" @@ -2470,7 +2547,7 @@ chai@^4.3.10, chai@^4.3.4, chai@^4.3.6, chai@^4.3.7: get-func-name "^2.0.2" loupe "^2.3.6" pathval "^1.1.1" - type-detect "^4.1.0" + type-detect "^4.0.8" chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" @@ -2516,7 +2593,7 @@ chokidar@3.5.3: optionalDependencies: fsevents "~2.3.2" -chokidar@^3.4.0, chokidar@^3.5.3: +chokidar@^3.4.0: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -2570,9 +2647,9 @@ cli-table3@^0.5.0: colors "^1.1.2" cli-table3@^0.6.0: - version "0.6.5" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" - integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== + version "0.6.4" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.4.tgz#d1c536b8a3f2e7bec58f67ac9e5769b1b30088b0" + integrity sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw== dependencies: string-width "^4.2.0" optionalDependencies: @@ -2728,9 +2805,9 @@ cookie@^0.4.1: integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== core-js-pure@^3.0.1: - version "3.38.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.38.1.tgz#e8534062a54b7221344884ba9b52474be495ada3" - integrity sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ== + version "3.36.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.36.1.tgz#1461c89e76116528b54eba20a0aff30164087a94" + integrity sha512-NXCvHvSVYSrewP0L5OhltzXeWFJLo2AL2TYnj6iLV3Bw8mM62wAQMNgUCRI6EBu6hVVpbCxmOPlxh1Ikw2PfUA== core-js@^2.4.0: version "2.6.12" @@ -2758,12 +2835,12 @@ cosmiconfig@^8.0.0: path-type "^4.0.0" cpu-features@~0.0.9: - version "0.0.10" - resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.10.tgz#9aae536db2710c7254d7ed67cb3cbc7d29ad79c5" - integrity sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA== + version "0.0.9" + resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.9.tgz#5226b92f0f1c63122b0a3eb84cb8335a4de499fc" + integrity sha512-AKjgn2rP2yJyfbepsmLfiYcmtNn/2eUvocUyM/09yB0YDiz39HteK/5/T4Onf0pmdYDMgkBoGvRLvEguzyL7wQ== dependencies: buildcheck "~0.0.6" - nan "^2.19.0" + nan "^2.17.0" crc-32@^1.2.0: version "1.2.2" @@ -2856,10 +2933,10 @@ death@^1.1.0: resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" integrity sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w== -debug@4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5: - version "4.3.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" - integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== +debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" @@ -2897,9 +2974,9 @@ decompress-response@^6.0.0: mimic-response "^3.1.0" deep-eql@^4.0.1, deep-eql@^4.1.3: - version "4.1.4" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.4.tgz#d0d3912865911bb8fac5afb4e3acfa6a28dc72b7" - integrity sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg== + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== dependencies: type-detect "^4.0.0" @@ -2964,7 +3041,7 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diff@^5.2.0: +diff@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== @@ -3088,9 +3165,9 @@ elliptic@6.5.4: minimalistic-crypto-utils "^1.0.1" elliptic@^6.5.2, elliptic@^6.5.4: - version "6.5.7" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" - integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== + version "6.5.5" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.5.tgz#c715e09f78b6923977610d4c2346d6ce22e6dded" + integrity sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -3127,10 +3204,10 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" -enhanced-resolve@^5.15.0: - version "5.17.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" - integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== +enhanced-resolve@^5.12.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787" + integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -3300,23 +3377,22 @@ eslint-import-resolver-node@^0.3.9: resolve "^1.22.4" eslint-import-resolver-typescript@^3.6.1: - version "3.6.3" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz#bb8e388f6afc0f940ce5d2c5fd4a3d147f038d9e" - integrity sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA== - dependencies: - "@nolyfill/is-core-module" "1.0.39" - debug "^4.3.5" - enhanced-resolve "^5.15.0" - eslint-module-utils "^2.8.1" - fast-glob "^3.3.2" - get-tsconfig "^4.7.5" - is-bun-module "^1.0.2" + version "3.6.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa" + integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg== + dependencies: + debug "^4.3.4" + enhanced-resolve "^5.12.0" + eslint-module-utils "^2.7.4" + fast-glob "^3.3.1" + get-tsconfig "^4.5.0" + is-core-module "^2.11.0" is-glob "^4.0.3" -eslint-module-utils@^2.8.0, eslint-module-utils@^2.8.1: - version "2.8.2" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz#2ecad69d71e1fa81f17f7f24d5d3e46b168de663" - integrity sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg== +eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" + integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== dependencies: debug "^3.2.7" @@ -3344,12 +3420,12 @@ eslint-plugin-import@^2.29.0: tsconfig-paths "^3.15.0" eslint-plugin-prettier@^5.0.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz#d1c8f972d8f60e414c25465c163d16f209411f95" - integrity sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw== + version "5.1.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz#17cfade9e732cef32b5f5be53bd4e07afd8e67e1" + integrity sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw== dependencies: prettier-linter-helpers "^1.0.0" - synckit "^0.9.1" + synckit "^0.8.6" eslint-scope@^7.2.2: version "7.2.2" @@ -3428,9 +3504,9 @@ esprima@^4.0.0: integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.4.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" - integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" @@ -3476,9 +3552,9 @@ eth-gas-reporter@^0.2.25: sync-request "^6.0.0" ethereum-bloom-filters@^1.0.6: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.2.0.tgz#8294f074c1a6cbd32c39d2cc77ce86ff14797dab" - integrity sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.1.0.tgz#b3fc1eb789509ee30db0bf99a2988ccacb8d0397" + integrity sha512-J1gDRkLpuGNvWYzWslBQR9cDV4nd4kfvVTE/Wy4Kkm4yb3EYRSlyi0eB/inTsSTTVyA0+HyzHgbr95Fn/Z1fSw== dependencies: "@noble/hashes" "^1.4.0" @@ -3514,14 +3590,14 @@ ethereum-cryptography@^1.0.3: "@scure/bip39" "1.1.1" ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" - integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== + version "2.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz#1352270ed3b339fe25af5ceeadcf1b9c8e30768a" + integrity sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA== dependencies: - "@noble/curves" "1.4.2" - "@noble/hashes" "1.4.0" - "@scure/bip32" "1.4.0" - "@scure/bip39" "1.3.0" + "@noble/curves" "1.3.0" + "@noble/hashes" "1.3.3" + "@scure/bip32" "1.3.3" + "@scure/bip39" "1.2.2" ethereum-waffle@^4.0.10: version "4.0.10" @@ -3762,7 +3838,7 @@ fast-diff@^1.1.2, fast-diff@^1.2.0: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== -fast-glob@^3.0.3, fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.2: +fast-glob@^3.0.3, fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.1, fast-glob@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -3783,11 +3859,6 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== -fast-uri@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" - integrity sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw== - fastq@^1.6.0: version "1.17.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" @@ -3802,10 +3873,10 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: to-regex-range "^5.0.1" @@ -3933,7 +4004,7 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^11.1.1, fs-extra@^11.2.0: +fs-extra@^11.1.1: version "11.2.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== @@ -4067,10 +4138,10 @@ get-symbol-description@^1.0.2: es-errors "^1.3.0" get-intrinsic "^1.2.4" -get-tsconfig@^4.7.5: - version "4.7.6" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.6.tgz#118fd5b7b9bae234cc7705a00cd771d7eb65d62a" - integrity sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA== +get-tsconfig@^4.5.0: + version "4.7.3" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.3.tgz#0498163d98f7b58484dd4906999c0c9d5f103f83" + integrity sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg== dependencies: resolve-pkg-maps "^1.0.0" @@ -4127,6 +4198,17 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +glob@8.1.0, glob@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" @@ -4150,17 +4232,6 @@ glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.3, glob@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" - integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - glob@~8.0.3: version "8.0.3" resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e" @@ -4371,13 +4442,13 @@ hardhat@=2.22.2: ws "^7.4.6" hardhat@^2.14.0: - version "2.22.9" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.9.tgz#d8f2720561dc60f5cc0ee80c82f9b1907fd61c88" - integrity sha512-sWiuI/yRdFUPfndIvL+2H18Vs2Gav0XacCFYY5msT5dHOWkhLxESJySIk9j83mXL31aXL8+UMA9OgViFLexklg== + version "2.22.7" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.7.tgz#3de0ce5074063cf468876c5e62f84c66d2408e8e" + integrity sha512-nrXQAl+qUr75TsCLDo8P41YXLc+5U7qQMMCIrbbmy1/uQaVPncdjDrD5BR0CENvHRj7EBqO+JkofpozXoIfJKg== dependencies: "@ethersproject/abi" "^5.1.2" "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/edr" "^0.5.2" + "@nomicfoundation/edr" "^0.5.0" "@nomicfoundation/ethereumjs-common" "4.0.4" "@nomicfoundation/ethereumjs-tx" "5.0.4" "@nomicfoundation/ethereumjs-util" "9.0.4" @@ -4419,6 +4490,55 @@ hardhat@^2.14.0: uuid "^8.3.2" ws "^7.4.6" +hardhat@^2.19.4: + version "2.22.5" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.5.tgz#7e1a4311fa9e34a1cfe337784eae06706f6469a5" + integrity sha512-9Zq+HonbXCSy6/a13GY1cgHglQRfh4qkzmj1tpPlhxJDwNVnhxlReV6K7hCWFKlOrV13EQwsdcD0rjcaQKWRZw== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" + "@nomicfoundation/edr" "^0.4.0" + "@nomicfoundation/ethereumjs-common" "4.0.4" + "@nomicfoundation/ethereumjs-tx" "5.0.4" + "@nomicfoundation/ethereumjs-util" "9.0.4" + "@nomicfoundation/solidity-analyzer" "^0.1.0" + "@sentry/node" "^5.18.1" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + adm-zip "^0.4.16" + aggregate-error "^3.0.0" + ansi-escapes "^4.3.0" + boxen "^5.1.2" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + ethereum-cryptography "^1.0.3" + ethereumjs-abi "^0.6.8" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "7.2.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + keccak "^3.0.2" + lodash "^4.17.11" + mnemonist "^0.38.0" + mocha "^10.0.0" + p-map "^4.0.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + tsort "0.0.1" + undici "^5.14.0" + uuid "^8.3.2" + ws "^7.4.6" + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -4487,7 +4607,7 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" -he@1.2.0, he@^1.2.0: +he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -4582,9 +4702,9 @@ ieee754@^1.1.13, ieee754@^1.2.1: integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.4: - version "5.3.2" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" - integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== ignore@~5.2.4: version "5.2.4" @@ -4602,9 +4722,9 @@ immediate@~3.2.3: integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== immutable@^4.0.0-rc.12: - version "4.3.7" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" - integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + version "4.3.5" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.5.tgz#f8b436e66d59f99760dc577f5c99a4fd2a5cc5a0" + integrity sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw== import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" @@ -4713,24 +4833,17 @@ is-buffer@^2.0.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-bun-module@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-bun-module/-/is-bun-module-1.1.0.tgz#a66b9830869437f6cdad440ba49ab6e4dc837269" - integrity sha512-4mTAVPlrXpaN3jtF0lsnPCMGnq4+qZjVIKq0HCpfcqf8OC1SM5oATCIAPM5V5FN05qp2NNnFndphmdZS9CV3hA== - dependencies: - semver "^7.6.3" - is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.13.0, is-core-module@^2.13.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" - integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== +is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: - hasown "^2.0.2" + hasown "^2.0.0" is-data-view@^1.0.1: version "1.0.1" @@ -5315,7 +5428,7 @@ lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@4.1.0, log-symbols@^4.1.0: +log-symbols@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== @@ -5342,6 +5455,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + lru_map@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" @@ -5465,11 +5585,11 @@ micro-ftch@^0.3.1: integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== micromatch@^4.0.4: - version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" - integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: - braces "^3.0.3" + braces "^3.0.2" picomatch "^2.3.1" miller-rabin@^4.0.0: @@ -5526,6 +5646,13 @@ minimatch@4.2.1: dependencies: brace-expansion "^1.1.7" +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + minimatch@9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -5533,7 +5660,7 @@ minimatch@9.0.3: dependencies: brace-expansion "^2.0.1" -minimatch@^5.0.1, minimatch@^5.1.6, minimatch@~5.1.2: +minimatch@^5.0.1, minimatch@~5.1.2: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== @@ -5582,30 +5709,30 @@ mnemonist@^0.38.0: obliterator "^2.0.0" mocha@^10.0.0, mocha@^10.2.0: - version "10.7.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.7.3.tgz#ae32003cabbd52b59aece17846056a68eb4b0752" - integrity sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A== - dependencies: - ansi-colors "^4.1.3" - browser-stdout "^1.3.1" - chokidar "^3.5.3" - debug "^4.3.5" - diff "^5.2.0" - escape-string-regexp "^4.0.0" - find-up "^5.0.0" - glob "^8.1.0" - he "^1.2.0" - js-yaml "^4.1.0" - log-symbols "^4.1.0" - minimatch "^5.1.6" - ms "^2.1.3" - serialize-javascript "^6.0.2" - strip-json-comments "^3.1.1" - supports-color "^8.1.1" - workerpool "^6.5.1" - yargs "^16.2.0" - yargs-parser "^20.2.9" - yargs-unparser "^2.0.0" + version "10.4.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.4.0.tgz#ed03db96ee9cfc6d20c56f8e2af07b961dbae261" + integrity sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "8.1.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" mocha@^9.0.2: version "9.2.2" @@ -5647,15 +5774,15 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1, ms@^2.1.3: +ms@2.1.3, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -nan@^2.18.0, nan@^2.19.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.20.0.tgz#08c5ea813dd54ed16e5bd6505bf42af4f7838ca3" - integrity sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw== +nan@^2.17.0, nan@^2.18.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0" + integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw== nanoid@3.3.1: version "3.3.1" @@ -5677,7 +5804,7 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -nise@^5.1.9: +nise@^5.1.5: version "5.1.9" resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.9.tgz#0cb73b5e4499d738231a473cd89bd8afbb618139" integrity sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww== @@ -5688,17 +5815,6 @@ nise@^5.1.9: just-extend "^6.2.0" path-to-regexp "^6.2.1" -nise@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/nise/-/nise-6.0.0.tgz#ae56fccb5d912037363c3b3f29ebbfa28bde8b48" - integrity sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg== - dependencies: - "@sinonjs/commons" "^3.0.0" - "@sinonjs/fake-timers" "^11.2.2" - "@sinonjs/text-encoding" "^0.7.2" - just-extend "^6.2.0" - path-to-regexp "^6.2.1" - node-addon-api@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" @@ -5729,9 +5845,9 @@ node-gyp-build@4.4.0: integrity sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ== node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: - version "4.8.1" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.1.tgz#976d3ad905e71b76086f4f0b0d3637fe79b6cda5" - integrity sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw== + version "4.8.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.0.tgz#3fee9c1731df4581a3f9ead74664369ff00d26dd" + integrity sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og== nofilter@^3.1.0: version "3.1.0" @@ -5774,9 +5890,9 @@ object-assign@^4.1.0: integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-inspect@^1.13.1: - version "1.13.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" - integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== object-keys@^1.1.1: version "1.1.1" @@ -6026,9 +6142,9 @@ performance-now@^2.1.0: integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== picocolors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" @@ -6075,12 +6191,13 @@ prettier-linter-helpers@^1.0.0: fast-diff "^1.1.2" prettier-plugin-solidity@^1.1.3: - version "1.4.1" - resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.4.1.tgz#8060baf18853a9e34d2e09e47e87b4f19e15afe9" - integrity sha512-Mq8EtfacVZ/0+uDKTtHZGW3Aa7vEbX/BNx63hmVg6YTiTXSiuKP0amj0G6pGwjmLaOfymWh3QgXEZkjQbU8QRg== + version "1.3.1" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.3.1.tgz#59944d3155b249f7f234dee29f433524b9a4abcf" + integrity sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA== dependencies: - "@solidity-parser/parser" "^0.18.0" + "@solidity-parser/parser" "^0.17.0" semver "^7.5.4" + solidity-comments-extractor "^0.0.8" prettier@^2.1.2, prettier@^2.3.1, prettier@^2.8.3: version "2.8.8" @@ -6088,9 +6205,9 @@ prettier@^2.1.2, prettier@^2.3.1, prettier@^2.8.3: integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== prettier@^3.0.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" - integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== + version "3.2.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" + integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== process-nextick-args@~2.0.0: version "2.0.1" @@ -6172,10 +6289,10 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -qs@^6.12.3, qs@^6.4.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" - integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== +qs@^6.11.2, qs@^6.4.0: + version "6.12.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.0.tgz#edd40c3b823995946a8a0b1f208669c7a200db77" + integrity sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg== dependencies: side-channel "^1.0.6" @@ -6567,10 +6684,17 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.4, semver@^7.3.7, semver@^7.5.1, semver@^7.5.2, semver@^7.5.4, semver@^7.6.2, semver@^7.6.3: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +semver@^7.3.4, semver@^7.5.1, semver@^7.5.2, semver@^7.5.4: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + +semver@^7.3.7: + version "7.6.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.1.tgz#60bfe090bf907a25aa8119a72b9f90ef7ca281b2" + integrity sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA== serialize-javascript@6.0.0: version "6.0.0" @@ -6579,13 +6703,6 @@ serialize-javascript@6.0.0: dependencies: randombytes "^2.1.0" -serialize-javascript@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" - integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== - dependencies: - randombytes "^2.1.0" - set-function-length@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" @@ -6681,28 +6798,16 @@ sinon-chai@^3.7.0: integrity sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g== sinon@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-17.0.2.tgz#470894bcc2d24b01bad539722ea46da949892405" - integrity sha512-uihLiaB9FhzesElPDFZA7hDcNABzsVHwr3YfmM9sBllVwab3l0ltGlRV1XhpNfIacNDLGD1QRZNLs5nU5+hTuA== - dependencies: - "@sinonjs/commons" "^3.0.1" - "@sinonjs/fake-timers" "^11.2.2" - "@sinonjs/samsam" "^8.0.0" - diff "^5.2.0" - nise "^5.1.9" - supports-color "^7" - -sinon@^18.0.0: - version "18.0.0" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-18.0.0.tgz#69ca293dbc3e82590a8b0d46c97f63ebc1e5fc01" - integrity sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA== + version "17.0.1" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-17.0.1.tgz#26b8ef719261bf8df43f925924cccc96748e407a" + integrity sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g== dependencies: - "@sinonjs/commons" "^3.0.1" + "@sinonjs/commons" "^3.0.0" "@sinonjs/fake-timers" "^11.2.2" "@sinonjs/samsam" "^8.0.0" - diff "^5.2.0" - nise "^6.0.0" - supports-color "^7" + diff "^5.1.0" + nise "^5.1.5" + supports-color "^7.2.0" slash@^3.0.0: version "3.0.0" @@ -6830,6 +6935,11 @@ solhint@^3.6.2: optionalDependencies: prettier "^2.8.3" +solidity-comments-extractor@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.8.tgz#f6e148ab0c49f30c1abcbecb8b8df01ed8e879f8" + integrity sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g== + solidity-coverage@^0.8.5: version "0.8.12" resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.12.tgz#c4fa2f64eff8ada7a1387b235d6b5b0e6c6985ed" @@ -7028,7 +7138,7 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== -supports-color@8.1.1, supports-color@^8.1.1: +supports-color@8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -7049,7 +7159,7 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7, supports-color@^7.1.0: +supports-color@^7.1.0, supports-color@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== @@ -7077,10 +7187,10 @@ sync-rpc@^1.2.1: dependencies: get-port "^3.1.0" -synckit@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.1.tgz#febbfbb6649979450131f64735aa3f6c14575c88" - integrity sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A== +synckit@^0.8.6: + version "0.8.8" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" + integrity sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ== dependencies: "@pkgr/core" "^0.1.0" tslib "^2.6.2" @@ -7325,9 +7435,9 @@ tslib@^1.9.3: integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.6.2: - version "2.7.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" - integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== tsort@0.0.1: version "0.0.1" @@ -7370,16 +7480,11 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@4.0.8: +type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-detect@^4.0.0, type-detect@^4.0.8, type-detect@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" - integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== - type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" @@ -7479,9 +7584,9 @@ typescript@^4.6.4: integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== typescript@^5.2.2: - version "5.5.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" - integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== + version "5.4.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.4.tgz#eb2471e7b0a5f1377523700a21669dce30c2d952" + integrity sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw== typical@^2.6.0, typical@^2.6.1: version "2.6.1" @@ -7504,9 +7609,9 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== uglify-js@^3.1.4: - version "3.19.2" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.2.tgz#319ae26a5fbd18d03c7dc02496cfa1d6f1cd4307" - integrity sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ== + version "3.17.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" + integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== unbox-primitive@^1.0.2: version "1.0.2" @@ -7518,10 +7623,10 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -undici-types@~6.19.2: - version "6.19.8" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" - integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== undici@^5.14.0: version "5.28.4" @@ -7530,11 +7635,6 @@ undici@^5.14.0: dependencies: "@fastify/busboy" "^2.0.0" -undici@^6.18.2: - version "6.19.8" - resolved "https://registry.yarnpkg.com/undici/-/undici-6.19.8.tgz#002d7c8a28f8cc3a44ff33c3d4be4d85e15d40e1" - integrity sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g== - universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -7550,7 +7650,7 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -uri-js@^4.2.2: +uri-js@^4.2.2, uri-js@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== @@ -7558,12 +7658,12 @@ uri-js@^4.2.2: punycode "^2.1.0" url@^0.11.0: - version "0.11.4" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.4.tgz#adca77b3562d56b72746e76b330b7f27b6721f3c" - integrity sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg== + version "0.11.3" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.3.tgz#6f495f4b935de40ce4a0a52faee8954244f3d3ad" + integrity sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw== dependencies: punycode "^1.4.1" - qs "^6.12.3" + qs "^6.11.2" utf-8-validate@5.0.7: version "5.0.7" @@ -7711,10 +7811,10 @@ workerpool@6.2.0: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== -workerpool@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" - integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== wrap-ansi@^7.0.0: version "7.0.0" @@ -7736,9 +7836,9 @@ ws@7.4.6: integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== ws@^7.4.6: - version "7.5.10" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" - integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== xhr2@0.1.3: version "0.1.3" @@ -7765,17 +7865,22 @@ yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== -yargs-parser@^20.2.2, yargs-parser@^20.2.9: +yargs-parser@^20.2.2: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-unparser@2.0.0, yargs-unparser@^2.0.0: +yargs-unparser@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== @@ -7785,7 +7890,7 @@ yargs-unparser@2.0.0, yargs-unparser@^2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" -yargs@16.2.0, yargs@^16.2.0: +yargs@16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -7809,13 +7914,20 @@ yocto-queue@^0.1.0: integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== yocto-queue@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" - integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== + version "1.0.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" + integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== + +zksync-ethers@^5.0.0: + version "5.8.0" + resolved "https://registry.yarnpkg.com/zksync-ethers/-/zksync-ethers-5.8.0.tgz#ff054345048f851c33cb6efcf2094f40d4da6063" + integrity sha512-/4qI5UElh0lspu0ew2IXBCO+O9kXEzZOM7JqvlfRWWGIUKZ+EDXnjIPgkH0y5/MnMT3FDq9koAAUCyZVWqHUJg== + dependencies: + ethers "~5.7.0" -zksync-ethers@^5.0.0, zksync-ethers@^5.9.0: - version "5.9.2" - resolved "https://registry.yarnpkg.com/zksync-ethers/-/zksync-ethers-5.9.2.tgz#1c5f34cb25ac0b040fd1a6118f2ba1c2c3bda090" - integrity sha512-Y2Mx6ovvxO6UdC2dePLguVzvNToOY8iLWeq5ne+jgGSJxAi/f4He/NF6FNsf6x1aWX0o8dy4Df8RcOQXAkj5qw== +zksync-ethers@^5.9.0: + version "5.9.0" + resolved "https://registry.yarnpkg.com/zksync-ethers/-/zksync-ethers-5.9.0.tgz#96dc29e4eaaf0aa70d927886fd6e1e4c545786e3" + integrity sha512-VnRUesrBcPBmiTYTAp+WreIazK2qCIJEHE7j8BiK+cDApHzjAfIXX+x8SXXJpG1npGJANxiJKnPwA5wjGZtCRg== dependencies: ethers "~5.7.0" From 0922be90563c6fd251a9a3ec67aa0de91f2539b5 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 27 Aug 2024 15:59:33 -0300 Subject: [PATCH 38/59] Update system contracts hashes --- system-contracts/SystemContractsHashes.json | 32 ++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index d6f552046..222613bac 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,49 +3,49 @@ "contractName": "AccountCodeStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x01000083f5c41c79561ef0eb3901e87e437aa97d6ff1e9148cf88bdcb3d79983", + "bytecodeHash": "0x010000838a9b03aa13f80383d59100a8dfc3d6faf7e4e99073d6275de45039ff", "sourceCodeHash": "0xd093d1595f6395c3d447c86e377d847690bcbd6b0e69488b4161286bf9e4ea82" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010007df5e1added77f71992b3523c8f41d0fae2d21a0144df70a8b19cbd73bb", + "bytecodeHash": "0x010007df4540d6434b5c2dd67689a25ebc8e9a3d7162c40b5a9c3c19912adcdb", "sourceCodeHash": "0x8462a9ddedbff81c6cf8fc3ac33500f4f416fc31b1f025d90bb760fa4ebca8a4" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004d3638948aa9391f1fec3e9dd6127531003496636506e9dd1d348475c6", + "bytecodeHash": "0x0100004daa4d6118f283a2388e93bf5523e55ead72a3e3899c3bab2f66095904", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100014fa5280d9df8df0b95b5d773771f90238c56fa7d107149b8b45053bb9e", + "bytecodeHash": "0x0100014feb0de348d8985ac02d9bc26d90306286c1f2cd21dea76962347ce89c", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x01000735a9539fdea7945d9993813db2ddaf18b7cfaa31d9591a128c1caf18ad", + "bytecodeHash": "0x010007339aa755e09b0084b18a613b36b97f459c4aeecacf8cac29409703871b", "sourceCodeHash": "0x3d6200608d8ee9ecd71f6d44f6e30197b0643374e225894c30f0b00d83e71bfb" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x01000049bba25ccf15dce4a4919e5bc6d26d2bab101ec8fec698316f10765e9c", + "bytecodeHash": "0x01000049808e071451bbf71429b9c1c723461186d5b136d5aa4f3bd3ea993861", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100058d1815df17a4900aeb68db2445d025cf41acc67795bf32582e60d7a92a", + "bytecodeHash": "0x0100058d69da9a1ba9e97d8d26a67967a39e1a9d50d55a4b6aace7d98877a485", "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { @@ -59,63 +59,63 @@ "contractName": "EvmGasManager", "bytecodePath": "artifacts-zk/contracts-preprocessed/EvmGasManager.sol/EvmGasManager.json", "sourceCodePath": "contracts-preprocessed/EvmGasManager.sol", - "bytecodeHash": "0x010000ed59ae506984e6d98e8e05afce8b2cdc336f1b8b179d4a72bb799375ac", + "bytecodeHash": "0x010000ed591827e22c0206f9e916090dc3a6f8890590dd164b169bb55bbb7095", "sourceCodeHash": "0x6e58be3f630adf305473e9a1844a448d9836322c10dc79e953a7ae319fc009b0" }, { "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x0100003998de054dfdabd41ecf2ad6f28463a94829f2c9aca382226ec50c6b5a", + "bytecodeHash": "0x01000039ceaa2800f6b0797bdb8df0c055448c03aa9582d51569908fcaefec06", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cf101e7f2d96b05f1f797c99de80271eb8c20e62ecf4311f24684cc20b", + "bytecodeHash": "0x010000cfb1bdccbc725fcaf6005aacc7501b1598f963da9cdad0f591be986cf2", "sourceCodeHash": "0xe07e6543ac09b86042eff5f9067df6db10a4fc039ecb56098a882ee1019c3031" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000299392a253d20178749eaa3ab9098b97ff7a7f1aff3a1ea89c4728d9315", + "bytecodeHash": "0x01000299b5db410894487bd33469d9da04b266770f0e2d4250ee750008671086", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x01000103e5cf0eab5df70d128f9310c40519e5e0209ad9570133640b84509e40", + "bytecodeHash": "0x01000103f3e83964bca357e6ebaf094adab722be60efe9b22d34a8e7ce6aada5", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005d1283cf6be4658b5ac84c33d1ab86a60df646b8e57d578c61a438b4d0", + "bytecodeHash": "0x0100005df596705b7040ed6356f4a7b17199d83a93e39894c62804e56d8a50f7", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000fb1ae585d33ac95fc980136cfff6245226fe2b98713c9092152c3b32c8", + "bytecodeHash": "0x010000fb1ef4ba579320638b7fa14ce87055900dc7d26b431d817057ba8277b5", "sourceCodeHash": "0x9ec18b6a78758b999f9acdca50b1f2464beac1cb317b7184017fd4e96ad7ec58" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000047046412295a727492d622b3ee861e577808994f5f06e2074e12ad12ca", + "bytecodeHash": "0x01000047bfe5e2f6b4a6ddab46dca4586dcd346153d525096b8438fe436dc675", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a5795c254a344b41852ca07da7dad3498865bb977c6982d6b79c65cfc9", + "bytecodeHash": "0x010001a5d33ef1caacbbbfcb8f996fe16158173325c093c9b377a16c59638ff1", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { From 0a17e16a22412b6a6719c67a051b30fccdbdaba3 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 27 Aug 2024 17:15:51 -0300 Subject: [PATCH 39/59] Add evm simulatro bytecode hash to the test deployer --- l1-contracts/src.ts/deploy-test-process.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/l1-contracts/src.ts/deploy-test-process.ts b/l1-contracts/src.ts/deploy-test-process.ts index 49b26e956..09965b3d8 100644 --- a/l1-contracts/src.ts/deploy-test-process.ts +++ b/l1-contracts/src.ts/deploy-test-process.ts @@ -66,6 +66,7 @@ export async function defaultDeployerForTests(deployWallet: Wallet, ownerAddress addresses: addressConfig, bootloaderBytecodeHash: L2_BOOTLOADER_BYTECODE_HASH, defaultAccountBytecodeHash: L2_DEFAULT_ACCOUNT_BYTECODE_HASH, + evmSimulatorBytecodeHash: L2_EVM_SIMULATOR_BYTECODE_HASH, }); } @@ -77,6 +78,7 @@ export async function defaultEraDeployerForTests(deployWallet: Wallet, ownerAddr addresses: addressConfig, bootloaderBytecodeHash: L2_BOOTLOADER_BYTECODE_HASH, defaultAccountBytecodeHash: L2_DEFAULT_ACCOUNT_BYTECODE_HASH, + evmSimulatorBytecodeHash: L2_EVM_SIMULATOR_BYTECODE_HASH, }); const l2_rpc_addr = "http://localhost:3050"; const web3Provider = new zkethers.Provider(l2_rpc_addr); From 8e0aa26c26299977d19f2c5515fe5c08dbff4d43 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 29 Aug 2024 12:22:11 -0300 Subject: [PATCH 40/59] Update evm interpreter contract to make sys calls when required --- system-contracts/contracts/EvmInterpreter.yul | 513 +++++++++++++----- 1 file changed, 385 insertions(+), 128 deletions(-) diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmInterpreter.yul index 71a9b09fc..2342c2a40 100644 --- a/system-contracts/contracts/EvmInterpreter.yul +++ b/system-contracts/contracts/EvmInterpreter.yul @@ -29,7 +29,20 @@ object "EVMInterpreter" { mstore(sub(offset, 64), 0x40) mstore(sub(offset, 32), len) - let success := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, sub(offset, 100), add(len, 100), 0, 0) + let farCallAbi := getFarCallABI( + 0, + 0, + sub(offset, 100), + add(len, 100), + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := DEPLOYER_SYSTEM_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { // This error should never happen @@ -390,12 +403,27 @@ object "EVMInterpreter" { mstore8(2, 0x4e) mstore8(3, 0x9e) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 4, 0, 64) + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 4, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { // Should never happen revert(0, 0) } + + returndatacopy(0,0,64) passGas := mload(0) isStatic := mload(32) @@ -567,6 +595,13 @@ object "EVMInterpreter" { gasToCharge := 0 } } + + function checkMemOverflowByOffset(offset, evmGasLeft) { + if gt(offset, MAX_POSSIBLE_MEM()) { + mstore(0, evmGasLeft) + revert(0, 32) + } + } function checkMemOverflow(location, evmGasLeft) { if gt(location, MAX_MEMORY_FRAME()) { @@ -659,12 +694,27 @@ object "EVMInterpreter" { mstore(4, key) mstore(36,currentValue) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 64) + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 68, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + + returndatacopy(0, 0, 64) isWarm := mload(0) originalValue := mload(32) @@ -746,19 +796,54 @@ object "EVMInterpreter" { 0xffffffffffffffffffffffffffffffffffffffff ) } + + function getFarCallABI( + dataOffset, + memoryPage, + dataStart, + dataLength, + gasPassed, + shardId, + forwardingMode, + isConstructorCall, + isSystemCall + ) -> ret { + let farCallAbi := 0 + farCallAbi := or(farCallAbi, dataOffset) + farCallAbi := or(farCallAbi, shl(64, dataStart)) + farCallAbi := or(farCallAbi, shl(96, dataLength)) + farCallAbi := or(farCallAbi, shl(192, gasPassed)) + farCallAbi := or(farCallAbi, shl(224, shardId)) + farCallAbi := or(farCallAbi, shl(232, forwardingMode)) + farCallAbi := or(farCallAbi, shl(248, 1)) + ret := farCallAbi + } function incrementNonce(addr) { - mstore8(0, 0x30) - mstore8(1, 0x63) - mstore8(2, 0x95) - mstore8(3, 0xc6) - mstore(4, addr) - - let result := call(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 0, 36, 0, 0) - - if iszero(result) { - revert(0, 0) - } + mstore8(0, 0x30) + mstore8(1, 0x63) + mstore8(2, 0x95) + mstore8(3, 0xc6) + mstore(4, addr) + + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 36, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := NONCE_HOLDER_SYSTEM_CONTRACT() + let result := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) + + if iszero(result) { + revert(0, 0) + } } function ensureAcceptableMemLocation(location) { @@ -790,16 +875,31 @@ object "EVMInterpreter" { mstore8(3, 0x78) mstore(4, addr) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 36, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + + returndatacopy(0, 0, 32) isWarm := mload(0) } - + function getNonce(addr) -> nonce { mstore8(0, 0xfb) mstore8(1, 0x1a) @@ -815,7 +915,7 @@ object "EVMInterpreter" { nonce := mload(0) } - + function getRawNonce(addr) -> nonce { mstore8(0, 0x5a) mstore8(1, 0xa9) @@ -831,7 +931,7 @@ object "EVMInterpreter" { nonce := mload(0) } - + function _isEVM(_addr) -> isEVM { // bytes4 selector = ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM.selector; (0x8c040477) // function isAccountEVM(address _addr) external view returns (bool); @@ -854,7 +954,7 @@ object "EVMInterpreter" { isEVM := mload(0) } - + function _pushEVMFrame(_passGas, _isStatic) { // function pushEVMFrame(uint256 _passGas, bool _isStatic) external let selector := 0xead77156 @@ -866,15 +966,47 @@ object "EVMInterpreter" { mstore(4, _passGas) mstore(36, _isStatic) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 0) + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 68, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) + + // let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } } - + function _popEVMFrame() { // function popEVMFrame() external + + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 4, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + + let to := EVM_GAS_MANAGER_CONTRACT() + // 0xe467d2f0 let selector := 0xe467d2f0 @@ -883,7 +1015,7 @@ object "EVMInterpreter" { mstore8(2, 0xd2) mstore8(3, 0xf0) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 4, 0, 0) + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) @@ -1326,7 +1458,7 @@ object "EVMInterpreter" { gasLeft := mload(0) } - function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeftOld) -> result, evmGasLeft { + function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt) -> result, evmGasLeft, addr { pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) _eraseReturndataPointer() @@ -1344,19 +1476,36 @@ object "EVMInterpreter" { sp := pushStackItem(sp, mload(sub(offset, 0x40)), evmGasLeftOld) sp := pushStackItem(sp, mload(sub(offset, 0x20)), evmGasLeftOld) - // Selector - mstore(sub(offset, 0x80), 0x5b16a23c) - // Arg1: address - mstore(sub(offset, 0x60), addr) - // Arg2: init code - // Where the arg starts (third word) - mstore(sub(offset, 0x40), 0x40) - // Length of the init code - mstore(sub(offset, 0x20), size) - _pushEVMFrame(gasForTheCall, false) - result := call(INF_PASS_GAS(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 0) + if isCreate2 { + // Create2EVM selector + mstore(sub(offset, 0x80), 0x4e96f4c0) + // salt + mstore(sub(offset, 0x60), salt) + // Where the arg starts (third word) + mstore(sub(offset, 0x40), 0x40) + // Length of the init code + mstore(sub(offset, 0x20), size) + + + result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) + } + + + if iszero(isCreate2) { + // CreateEVM selector + mstore(sub(offset, 0x60), 0xff311601) + // Where the arg starts (second word) + mstore(sub(offset, 0x40), 0x20) + // Length of the init code + mstore(sub(offset, 0x20), size) + + + result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) + } + + addr := mload(0) let gasLeft switch result @@ -1372,18 +1521,6 @@ object "EVMInterpreter" { _popEVMFrame() - switch result - case 1 { - incrementNonce(address()) - } - default { - switch isEOA(address()) - case 1 { - incrementNonce(address()) - } - default {} - } - let back popStackCheck(sp, evmGasLeft, 4) @@ -1451,7 +1588,7 @@ object "EVMInterpreter" { size, sp := popStackItemWithoutCheck(sp) checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) - + checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { @@ -1472,10 +1609,8 @@ object "EVMInterpreter" { ) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - let addr := getNewAddress(address()) - - let result - result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + let result, addr + result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,false,0) switch result case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } @@ -1532,7 +1667,7 @@ object "EVMInterpreter" { 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ) - result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, true, salt) } @@ -3385,13 +3520,28 @@ object "EVMInterpreter" { mstore8(2, 0x4e) mstore8(3, 0x9e) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 4, 0, 64) + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 4, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { // Should never happen revert(0, 0) } - + + returndatacopy(0,0,64) + passGas := mload(0) isStatic := mload(32) @@ -3562,6 +3712,13 @@ object "EVMInterpreter" { gasToCharge := 0 } } + + function checkMemOverflowByOffset(offset, evmGasLeft) { + if gt(offset, MAX_POSSIBLE_MEM()) { + mstore(0, evmGasLeft) + revert(0, 32) + } + } function checkMemOverflow(location, evmGasLeft) { if gt(location, MAX_MEMORY_FRAME()) { @@ -3654,12 +3811,27 @@ object "EVMInterpreter" { mstore(4, key) mstore(36,currentValue) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 64) + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 68, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + + returndatacopy(0, 0, 64) isWarm := mload(0) originalValue := mload(32) @@ -3741,6 +3913,28 @@ object "EVMInterpreter" { 0xffffffffffffffffffffffffffffffffffffffff ) } + + function getFarCallABI( + dataOffset, + memoryPage, + dataStart, + dataLength, + gasPassed, + shardId, + forwardingMode, + isConstructorCall, + isSystemCall + ) -> ret { + let farCallAbi := 0 + farCallAbi := or(farCallAbi, dataOffset) + farCallAbi := or(farCallAbi, shl(64, dataStart)) + farCallAbi := or(farCallAbi, shl(96, dataLength)) + farCallAbi := or(farCallAbi, shl(192, gasPassed)) + farCallAbi := or(farCallAbi, shl(224, shardId)) + farCallAbi := or(farCallAbi, shl(232, forwardingMode)) + farCallAbi := or(farCallAbi, shl(248, 1)) + ret := farCallAbi + } function incrementNonce(addr) { mstore8(0, 0x30) @@ -3749,7 +3943,20 @@ object "EVMInterpreter" { mstore8(3, 0xc6) mstore(4, addr) - let result := call(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 0, 36, 0, 0) + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 36, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := NONCE_HOLDER_SYSTEM_CONTRACT() + let result := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(result) { revert(0, 0) @@ -3785,13 +3992,28 @@ object "EVMInterpreter" { mstore8(3, 0x78) mstore(4, addr) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 36, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } - + + returndatacopy(0, 0, 32) + isWarm := mload(0) } @@ -3861,7 +4083,23 @@ object "EVMInterpreter" { mstore(4, _passGas) mstore(36, _isStatic) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 0) + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 68, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) + + // let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) @@ -3870,6 +4108,22 @@ object "EVMInterpreter" { function _popEVMFrame() { // function popEVMFrame() external + + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 4, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + + let to := EVM_GAS_MANAGER_CONTRACT() + // 0xe467d2f0 let selector := 0xe467d2f0 @@ -3878,7 +4132,7 @@ object "EVMInterpreter" { mstore8(2, 0xd2) mstore8(3, 0xf0) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 4, 0, 0) + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) @@ -4321,76 +4575,81 @@ object "EVMInterpreter" { gasLeft := mload(0) } - function $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeftOld) -> result, evmGasLeft { - pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) - - _eraseReturndataPointer() - - let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) - - if lt(selfbalance(),value) { - revertWithGas(evmGasLeftOld) - } - - offset := add(MEM_OFFSET_INNER(), offset) - - sp := pushStackItem(sp, mload(sub(offset, 0x80)), evmGasLeftOld) - sp := pushStackItem(sp, mload(sub(offset, 0x60)), evmGasLeftOld) - sp := pushStackItem(sp, mload(sub(offset, 0x40)), evmGasLeftOld) - sp := pushStackItem(sp, mload(sub(offset, 0x20)), evmGasLeftOld) - - // Selector - mstore(sub(offset, 0x80), 0x5b16a23c) - // Arg1: address - mstore(sub(offset, 0x60), addr) - // Arg2: init code + function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt) -> result, evmGasLeft, addr { + pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) + + _eraseReturndataPointer() + + let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) + + if lt(selfbalance(),value) { + revertWithGas(evmGasLeftOld) + } + + offset := add(MEM_OFFSET_INNER(), offset) + + sp := pushStackItem(sp, mload(sub(offset, 0x80)), evmGasLeftOld) + sp := pushStackItem(sp, mload(sub(offset, 0x60)), evmGasLeftOld) + sp := pushStackItem(sp, mload(sub(offset, 0x40)), evmGasLeftOld) + sp := pushStackItem(sp, mload(sub(offset, 0x20)), evmGasLeftOld) + + _pushEVMFrame(gasForTheCall, false) + + if isCreate2 { + // Create2EVM selector + mstore(sub(offset, 0x80), 0x4e96f4c0) + // salt + mstore(sub(offset, 0x60), salt) // Where the arg starts (third word) mstore(sub(offset, 0x40), 0x40) // Length of the init code mstore(sub(offset, 0x20), size) - - _pushEVMFrame(gasForTheCall, false) - - result := call(INF_PASS_GAS(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 0) - - let gasLeft - switch result - case 0 { - gasLeft := _saveReturndataAfterEVMCall(0, 0) - } - default { - gasLeft := _fetchConstructorReturnGas() - } - - let gasUsed := sub(gasForTheCall, gasLeft) - evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - - _popEVMFrame() - - switch result - case 1 { - incrementNonce(address()) + + + result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) + } + + + if iszero(isCreate2) { + // CreateEVM selector + mstore(sub(offset, 0x60), 0xff311601) + // Where the arg starts (second word) + mstore(sub(offset, 0x40), 0x20) + // Length of the init code + mstore(sub(offset, 0x20), size) + + + result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) + } + + addr := mload(0) + + let gasLeft + switch result + case 0 { + gasLeft := _saveReturndataAfterEVMCall(0, 0) } default { - switch isEOA(address()) - case 1 { - incrementNonce(address()) - } - default {} + gasLeft := _fetchConstructorReturnGas() } - - let back - - popStackCheck(sp, evmGasLeft, 4) - back, sp := popStackItemWithoutCheck(sp) - mstore(sub(offset, 0x20), back) - back, sp := popStackItemWithoutCheck(sp) - mstore(sub(offset, 0x40), back) - back, sp := popStackItemWithoutCheck(sp) - mstore(sub(offset, 0x60), back) - back, sp := popStackItemWithoutCheck(sp) - mstore(sub(offset, 0x80), back) - } + + let gasUsed := sub(gasForTheCall, gasLeft) + evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) + + _popEVMFrame() + + let back + + popStackCheck(sp, evmGasLeft, 4) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x20), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x40), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x60), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x80), back) + } function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { evmGasLeft := chargeGas(evmGas, 100) @@ -4467,10 +4726,8 @@ object "EVMInterpreter" { ) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - let addr := getNewAddress(address()) - - let result - result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + let result, addr + result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,false,0) switch result case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } @@ -4527,7 +4784,7 @@ object "EVMInterpreter" { 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ) - result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(addr, offset, size, sp, value, evmGasLeft) + result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt) } From 2d95a3b12aba3e490754320425f7369d7f283748 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 29 Aug 2024 12:23:53 -0300 Subject: [PATCH 41/59] Add modifier for functions that need to be called only by sys calls --- .../contracts/ContractDeployer.sol | 21 ++++++++++++------- system-contracts/contracts/EvmGasManager.sol | 2 ++ .../interfaces/IContractDeployer.sol | 2 -- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 100662e2c..b002013cf 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -39,7 +39,13 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { uint256 public constructorReturnGas; - function setDeployedCode(uint256 constructorGasLeft, bytes calldata paddedNewDeployedCode) external { + modifier onlySystemEvm() { + require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender), "only system evm"); + require(SystemContractHelper.isSystemCall(), "This method require system call flag"); + _; + } + + function setDeployedCode(uint256 constructorGasLeft, bytes calldata paddedNewDeployedCode) external onlySystemEvm { require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender)); uint256 bytecodeLen = uint256(bytes32(paddedNewDeployedCode[:32])); @@ -189,9 +195,15 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { function createEVM(bytes calldata _initCode) external payable override returns (address) { // If the account is an EOA, use the min nonce. If it's a contract, use deployment nonce // Subtract 1 for EOA since the nonce has already been incremented for this transaction + + uint256 deploymentNonce = NONCE_HOLDER_SYSTEM_CONTRACT.getDeploymentNonce(msg.sender); + if ((msg.sender != tx.origin) && deploymentNonce == 0) { + NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); + } + uint256 senderNonce = msg.sender == tx.origin ? NONCE_HOLDER_SYSTEM_CONTRACT.getMinNonce(msg.sender) - 1 - : NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender) + 1; + : NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); address newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); _evmDeployOnAddress(newAddress, _initCode); return newAddress; @@ -213,11 +225,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { return newAddress; } - function createEVMInternal(address _newAddress, bytes calldata _initCode) external payable { - require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender)); - _evmDeployOnAddress(_newAddress, _initCode); - } - /// @notice Deploys a contract account with similar address derivation rules to the EVM's `CREATE2` opcode. /// @param _salt The CREATE2 salt /// @param _bytecodeHash The correctly formatted hash of the bytecode. diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index 80fe8f90c..8825bcfa7 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.0; import {ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "./Constants.sol"; +import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; // We consider all the contracts (including system ones) as warm. uint160 constant PRECOMPILES_END = 0xffff; @@ -80,6 +81,7 @@ contract EvmGasManager { modifier onlySystemEvm() { require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender), "only system evm"); + require(SystemContractHelper.isSystemCall(), "This method require system call flag"); _; } diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index 6328d68b6..6fe0ae6c1 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -95,8 +95,6 @@ interface IContractDeployer { function create2EVM(bytes32 _salt, bytes calldata _initCode) external payable returns (address); - function createEVMInternal(address _newAddress, bytes calldata _initCode) external payable; - function evmCodeHash(address) external view returns (bytes32); function setDeployedCode(uint256 constructorGasLeft, bytes calldata newDeployedCode) external; From f3af76314e676fb34ead17cbdee0647ed7821db4 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 29 Aug 2024 12:24:39 -0300 Subject: [PATCH 42/59] Update increment nonce function to yield unauthorized error --- system-contracts/contracts/NonceHolder.sol | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/system-contracts/contracts/NonceHolder.sol b/system-contracts/contracts/NonceHolder.sol index 4d800d50b..232c3e480 100644 --- a/system-contracts/contracts/NonceHolder.sol +++ b/system-contracts/contracts/NonceHolder.sol @@ -7,8 +7,8 @@ pragma solidity 0.8.24; import {INonceHolder} from "./interfaces/INonceHolder.sol"; import {IContractDeployer} from "./interfaces/IContractDeployer.sol"; import {SystemContractBase} from "./abstract/SystemContractBase.sol"; -import {DEPLOYER_SYSTEM_CONTRACT, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "./Constants.sol"; -import {NonceIncreaseError, ZeroNonceError, NonceJumpError, ValueMismatch, NonceAlreadyUsed, NonceNotUsed} from "./SystemContractErrors.sol"; +import {DEPLOYER_SYSTEM_CONTRACT} from "./Constants.sol"; +import {NonceIncreaseError, ZeroNonceError, NonceJumpError, ValueMismatch, NonceAlreadyUsed, NonceNotUsed, Unauthorized} from "./SystemContractErrors.sol"; /** * @author Matter Labs @@ -144,11 +144,9 @@ contract NonceHolder is INonceHolder, SystemContractBase { /// @param _address The address of the account which to return the deploy nonce for. /// @return prevDeploymentNonce The deployment nonce at the time this function is called. function incrementDeploymentNonce(address _address) external returns (uint256 prevDeploymentNonce) { - require( - msg.sender == address(DEPLOYER_SYSTEM_CONTRACT) || - ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender), - "Only the contract deployer can increment the deployment nonce" - ); + if (msg.sender != address(DEPLOYER_SYSTEM_CONTRACT)) { + revert Unauthorized(msg.sender); + } uint256 addressAsKey = uint256(uint160(_address)); uint256 oldRawNonce = rawNonces[addressAsKey]; From 75f9287b5de96652cb9353921a40b950f1d26450 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 29 Aug 2024 12:24:50 -0300 Subject: [PATCH 43/59] Fix lint errors --- .../deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol | 3 +-- system-contracts/contracts/libraries/SystemContractHelper.sol | 1 + system-contracts/contracts/libraries/Utils.sol | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol b/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol index 3810805c8..0a7e20a53 100644 --- a/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol +++ b/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -// solhint-disable no-console +// solhint-disable no-console, gas-struct-packing, gas-custom-errors import {Script, console2 as console} from "forge-std/Script.sol"; import {stdToml} from "forge-std/StdToml.sol"; @@ -13,7 +13,6 @@ import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; import {L1SharedBridge} from "contracts/bridge/L1SharedBridge.sol"; import {IStateTransitionManager} from "contracts/state-transition/IStateTransitionManager.sol"; import {IGovernance} from "contracts/governance/IGovernance.sol"; -import {IERC20} from "forge-std/interfaces/IERC20.sol"; import {Utils} from "./Utils.sol"; /** diff --git a/system-contracts/contracts/libraries/SystemContractHelper.sol b/system-contracts/contracts/libraries/SystemContractHelper.sol index 317f138bf..43320c0ab 100644 --- a/system-contracts/contracts/libraries/SystemContractHelper.sol +++ b/system-contracts/contracts/libraries/SystemContractHelper.sol @@ -376,6 +376,7 @@ library SystemContractHelper { } uint32 dataLength = uint32(Utils.safeCastToU32(data.length)); + // solhint-disable func-named-parameters uint256 farCallAbi = SystemContractsCaller.getFarCallABI( 0, 0, diff --git a/system-contracts/contracts/libraries/Utils.sol b/system-contracts/contracts/libraries/Utils.sol index 7ffb2dc73..07e62476a 100644 --- a/system-contracts/contracts/libraries/Utils.sol +++ b/system-contracts/contracts/libraries/Utils.sol @@ -2,6 +2,8 @@ // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.20; +// solhint-disable gas-custom-errors + import {EfficientCall} from "./EfficientCall.sol"; import {RLPEncoder} from "./RLPEncoder.sol"; import {MalformedBytecode, BytecodeError, Overflow} from "../SystemContractErrors.sol"; @@ -130,6 +132,7 @@ library Utils { uint256 internal constant MAX_EVM_BYTECODE_LENGTH = (2 ** 16) - 1; function hashEVMBytecode(bytes memory _bytecode) internal view returns (bytes32 hashedEVMBytecode) { + // solhint-disable gas-custom-errors require(_bytecode.length <= MAX_EVM_BYTECODE_LENGTH, "po"); hashedEVMBytecode = sha256(_bytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; From d56209bd827808cf1a47f63f8aaebd5c603ac1db Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Thu, 29 Aug 2024 12:27:08 -0300 Subject: [PATCH 44/59] Update system contracts hashes --- system-contracts/SystemContractsHashes.json | 42 ++++++++++----------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 6437cbfe1..eedf70cb4 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,49 +3,49 @@ "contractName": "AccountCodeStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x0100008327e5be781440768ce3bfe21448e54fe87fc2a4a74bc16e0ca3dfa0c7", + "bytecodeHash": "0x0100008312026f2cfaeeb3a9b626e5317d0952371b67e17e0f018f15ba89cdc2", "sourceCodeHash": "0xc92c3beabb281421f2d6dc9e46f9ba83b9d46f55a4c1d6799dbec2f57c92b98a" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010007df9ec51168b7cd1e319792b7242a03bc8832650b5d6cd22b9f2e79f969", + "bytecodeHash": "0x010007df7ae2e4ece09fe9cdc03c112be3bb6ecc048a53b1409cfab089f670db", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004d8aa51903cd6fbbda8e893c6a161fdf565dca00a344ae35ec1311bce6", + "bytecodeHash": "0x0100004dbc6880547bd7ca3dfd987979e377b0e7d16e51bf0f6b187dad05109f", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100014f2ef94f48c9e891d2aea570d6cf851a461c0ad75fed863ae366f2613e", + "bytecodeHash": "0x0100014f624a3e224929d6b036dbd64e3de4c68ca61d225f48c8222e09477f0f", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010007331cc6b52bfd3587544b8ae82bc4f81c645582e777ee155a50d0b568eb", - "sourceCodeHash": "0x4be12df5b01cc51305357171ff969ff20728a5e913c1b1d22682054ac29692b1" + "bytecodeHash": "0x01000765b21f3e93da0beb7987904f82bd64d691146fcd9326735f10ea62e533", + "sourceCodeHash": "0x20d42c32468d61bf57fe2067ba5ebaa70d4060583b339e2df2958e72e7869650" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x01000049f3e19c118c6e7a0dde85fdf27dfefbcbbd9a8309062b16f69f53370f", + "bytecodeHash": "0x01000049b107e75dfd4df73357da5e7efe0582849ecfd1583ea8cc415252cdf1", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100058dbda1b3dd8b6691a346a813ead22aa55c5a14a399e1ff2f4dd3157fd2", + "bytecodeHash": "0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2", "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { @@ -59,63 +59,63 @@ "contractName": "EvmGasManager", "bytecodePath": "artifacts-zk/contracts-preprocessed/EvmGasManager.sol/EvmGasManager.json", "sourceCodePath": "contracts-preprocessed/EvmGasManager.sol", - "bytecodeHash": "0x010000edeb86e30abd239ed6fd837eae4f896a696d03005c5170b479427f7c68", - "sourceCodeHash": "0x6e58be3f630adf305473e9a1844a448d9836322c10dc79e953a7ae319fc009b0" + "bytecodeHash": "0x010001015b890ae21f91d270229a4c3aa6fd6ed6b209a1bd7d64b5accebe07f5", + "sourceCodeHash": "0xea3433435888b4fc1195386adb5bf5ca86ee8e4e1472b0eaeef6e907fd4aae6a" }, { "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x010000396075bffb5a7c0791bc4d67edb4f329dccaf17c136bd2b589b8ddf1e5", + "bytecodeHash": "0x01000039194d946e10393e585e587a0fed12a0b67f2a44600c81c0c07bb3e10e", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cf549827de27a8720c23fd1bcc6ded41b519901295c88b393b2412e8a6", + "bytecodeHash": "0x010000cfc53c719b7e5bec45883cf662e9a9099d016fba16bfe03b9e65f2b722", "sourceCodeHash": "0xe07e6543ac09b86042eff5f9067df6db10a4fc039ecb56098a882ee1019c3031" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x0100029983988986257e9957c0a711ae053cafb1db72215fc76506929e731ead", + "bytecodeHash": "0x01000299800a4edde1beaefff3e07af2387d0b34f2dfbcdf4ed1d87c0888ae90", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x01000103f69d5d23530d5645f97ab1dbe345837eb2376c506834bc3e9ca725df", + "bytecodeHash": "0x01000103c7807def7581dcf186b53df739e3b4c5d93b13a96741e7295e2e3f02", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005dd389a9aa7cbce6c7912bb0ac8cc094b209e25c5558ace6c3ff5a0fea", + "bytecodeHash": "0x0100005d99f6a76cec4466f3e1f95ee53731a64053035da02b287854a8a6a1a3", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000fb1c1d761706c3d15f2ab954facb23f162ed4fbd8e90ee34e571c76dbc", - "sourceCodeHash": "0x9ec18b6a78758b999f9acdca50b1f2464beac1cb317b7184017fd4e96ad7ec58" + "bytecodeHash": "0x010000d90192a1e931774c502cd530a5e950001e8f6fd8324c3a6767ad473ba9", + "sourceCodeHash": "0xff1ab1ce15c2e54954077315618822ec8deaeaae79ba4e2899518b8713a7234e" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x0100004720ac8a115256bd5233bd2c6a2f6409aa728868a077dda5937763de12", + "bytecodeHash": "0x01000047524067c7075952b5ebc383b3848e7a914164db9e7133c436ec2fd00e", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a5ad469d65662291b624c41c60af654b532a1b924086e9b49ff5976164", + "bytecodeHash": "0x010001a5a7920f9eac0b72744e73310ed60294df349fb9028ef3f5eb2dfab0aa", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { @@ -129,8 +129,8 @@ "contractName": "EvmInterpreter", "bytecodePath": "contracts-preprocessed/artifacts/EvmInterpreter.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmInterpreter.yul", - "bytecodeHash": "0x01000f196acd122635a752fcb275be0cc95fd3bba348c1d0908a517fe316418e", - "sourceCodeHash": "0x068f1229b92e0f3930231782f106a9889b8281b6750cca26d0375b6435d1fdaa" + "bytecodeHash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", + "sourceCodeHash": "0x4e16a8c65c4c5c3124dcfa2871da72a0c15744e524086a8c9dc46d7be164d539" }, { "contractName": "CodeOracle", From 5e6211a5d41232008059c20faaf2e929ca4c8abc Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Tue, 10 Sep 2024 12:48:04 -0300 Subject: [PATCH 45/59] Add preprocess script and template files --- .../contracts/EvmInterpreter.template.yul | 169 ++ system-contracts/contracts/EvmInterpreter.yul | 1517 +++++++---------- .../EvmInterpreterFunctions.template.yul | 1467 ++++++++++++++++ .../contracts/EvmInterpreterLoop.template.yul | 1465 ++++++++++++++++ system-contracts/package.json | 1 + .../scripts/preprocess-interpreter.ts | 21 + 6 files changed, 3736 insertions(+), 904 deletions(-) create mode 100644 system-contracts/contracts/EvmInterpreter.template.yul create mode 100644 system-contracts/contracts/EvmInterpreterFunctions.template.yul create mode 100644 system-contracts/contracts/EvmInterpreterLoop.template.yul create mode 100644 system-contracts/scripts/preprocess-interpreter.ts diff --git a/system-contracts/contracts/EvmInterpreter.template.yul b/system-contracts/contracts/EvmInterpreter.template.yul new file mode 100644 index 000000000..0aed3e039 --- /dev/null +++ b/system-contracts/contracts/EvmInterpreter.template.yul @@ -0,0 +1,169 @@ +object "EVMInterpreter" { + code { + /// @dev This function is used to get the initCode. + /// @dev It assumes that the initCode has been passed via the calldata and so we use the pointer + /// to obtain the bytecode. + function getConstructorBytecode() { + let bytecodeLengthOffset := BYTECODE_OFFSET() + let bytecodeOffset := add(BYTECODE_OFFSET(), 32) + + loadCalldataIntoActivePtr() + + let size := getActivePtrDataSize() + mstore(bytecodeLengthOffset, size) + + copyActivePtrData(bytecodeOffset, 0, size) + } + + // Note that this function modifies EVM memory and does not restore it. It is expected that + // it is the last called function during execution. + function setDeployedCode(gasLeft, offset, len) { + // This error should never be triggered + // require(offset > 100, "Offset too small"); + + mstore(sub(offset, 100), 0xD9EB76B200000000000000000000000000000000000000000000000000000000) + mstore(sub(offset, 96), gasLeft) + mstore(sub(offset, 64), 0x40) + mstore(sub(offset, 32), len) + + let farCallAbi := getFarCallABI( + 0, + 0, + sub(offset, 100), + add(len, 100), + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := DEPLOYER_SYSTEM_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + } + + function padBytecode(offset, len) -> blobOffset, blobLen { + blobOffset := sub(offset, 32) + let trueLastByte := add(offset, len) + + mstore(blobOffset, len) + // clearing out additional bytes + mstore(trueLastByte, 0) + mstore(add(trueLastByte, 32), 0) + + blobLen := add(len, 32) + + if iszero(eq(mod(blobLen, 32), 0)) { + blobLen := add(blobLen, sub(32, mod(blobLen, 32))) + } + + // Now it is divisible by 32, but we must make sure that the number of 32 byte words is odd + if iszero(eq(mod(blobLen, 64), 32)) { + blobLen := add(blobLen, 32) + } + } + + function validateCorrectBytecode(offset, len, gasToReturn) -> returnGas { + if len { + let firstByte := shr(248, mload(offset)) + if eq(firstByte, 0xEF) { + revert(0, 0) + } + } + + let gasForCode := mul(len, 200) + returnGas := chargeGas(gasToReturn, gasForCode) + } + + + + function simulate( + isCallerEVM, + evmGasLeft, + isStatic, + ) -> returnOffset, returnLen, retGasLeft { + + returnOffset := MEM_OFFSET_INNER() + returnLen := 0 + + + + retGasLeft := evmGasLeft + } + + //////////////////////////////////////////////////////////////// + // FALLBACK + //////////////////////////////////////////////////////////////// + + let evmGasLeft, isStatic, isCallerEVM := consumeEvmFrame() + + if isStatic { + revert(0, 0) + } + + getConstructorBytecode() + + if iszero(isCallerEVM) { + evmGasLeft := getEVMGas() + } + + let offset, len, gasToReturn := simulate(isCallerEVM, evmGasLeft, false) + + gasToReturn := validateCorrectBytecode(offset, len, gasToReturn) + + offset, len := padBytecode(offset, len) + + setDeployedCode(gasToReturn, offset, len) + } + object "EVMInterpreter_deployed" { + code { + + + function $llvm_NoInline_llvm$_simulate( + isCallerEVM, + evmGasLeft, + isStatic, + ) -> returnOffset, returnLen { + + returnOffset := MEM_OFFSET_INNER() + returnLen := 0 + + + + if eq(isCallerEVM, 1) { + // Includes gas + returnOffset := sub(returnOffset, 32) + checkOverflow(returnLen, 32, evmGasLeft) + returnLen := add(returnLen, 32) + + mstore(returnOffset, evmGasLeft) + } + } + + //////////////////////////////////////////////////////////////// + // FALLBACK + //////////////////////////////////////////////////////////////// + + let evmGasLeft, isStatic, isCallerEVM := consumeEvmFrame() + + if iszero(isCallerEVM) { + evmGasLeft := getEVMGas() + isStatic := getIsStaticFromCallFlags() + } + + // First, copy the contract's bytecode to be executed into tEdhe `BYTECODE_OFFSET` + // segment of memory. + getDeployedBytecode() + + pop($llvm_AlwaysInline_llvm$_warmAddress(address())) + + let returnOffset, returnLen := $llvm_NoInline_llvm$_simulate(isCallerEVM, evmGasLeft, isStatic) + return(returnOffset, returnLen) + } + } +} diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmInterpreter.yul index 2342c2a40..077560eb2 100644 --- a/system-contracts/contracts/EvmInterpreter.yul +++ b/system-contracts/contracts/EvmInterpreter.yul @@ -21,10 +21,7 @@ object "EVMInterpreter" { // This error should never be triggered // require(offset > 100, "Offset too small"); - mstore8(sub(offset, 100), 0xd9) - mstore8(sub(offset, 99), 0xeb) - mstore8(sub(offset, 98), 0x76) - mstore8(sub(offset, 97), 0xb2) + mstore(sub(offset, 100), 0xD9EB76B200000000000000000000000000000000000000000000000000000000) mstore(sub(offset, 96), gasLeft) mstore(sub(offset, 64), 0x40) mstore(sub(offset, 32), len) @@ -73,8 +70,6 @@ object "EVMInterpreter" { function validateCorrectBytecode(offset, len, gasToReturn) -> returnGas { if len { - // let firstByte := shr(mload(offset), 248) - // FIXME: Check this. let firstByte := shr(248, mload(offset)) if eq(firstByte, 0xEF) { revert(0, 0) @@ -163,7 +158,6 @@ object "EVMInterpreter" { // It is the responsibility of the caller to ensure that ip >= BYTECODE_OFFSET + 32 function readIP(ip,maxAcceptablePos) -> opcode { - // TODO: Why not do this at the beginning once instead of every time? if gt(ip, maxAcceptablePos) { revert(0, 0) } @@ -251,11 +245,8 @@ object "EVMInterpreter" { } } - function popPushStackCheck(sp, evmGasLeft, numInputs) { - let popCheck := lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) - let pushOffset := sub(sp, mul(0x20, numInputs)) - let pushCheck := or(gt(pushOffset, BYTECODE_OFFSET()), eq(pushOffset, BYTECODE_OFFSET())) - if or(popCheck, pushCheck) { + function pushStackCheck(sp, evmGasLeft, numInputs) { + if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { revertWithGas(evmGasLeft) } } @@ -289,11 +280,7 @@ object "EVMInterpreter" { } function _getRawCodeHash(account) -> hash { - // TODO: Unhardcode this selector - mstore8(0, 0x4d) - mstore8(1, 0xe2) - mstore8(2, 0xe4) - mstore8(3, 0x68) + mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) @@ -308,12 +295,7 @@ object "EVMInterpreter" { function _getCodeHash(account) -> hash { // function getCodeHash(uint256 _input) external view override returns (bytes32) - // 0xe03fe177 - // TODO: Unhardcode this selector - mstore8(0, 0xe0) - mstore8(1, 0x3f) - mstore8(2, 0xe1) - mstore8(3, 0x77) + mstore(0, 0xE03FE17700000000000000000000000000000000000000000000000000000000) mstore(4, account) let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) @@ -328,7 +310,6 @@ object "EVMInterpreter" { function getIsStaticFromCallFlags() -> isStatic { isStatic := verbatim_0i_1o("get_global::call_flags") - // TODO: make it a constnat isStatic := iszero(iszero(and(isStatic, 0x04))) } @@ -365,24 +346,17 @@ object "EVMInterpreter" { function _fetchDeployedCodeLen(addr) -> codeLen { let codeHash := _getRawCodeHash(addr) - mstore(0, codeHash) - - let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) - - switch iszero(success) + switch shr(248, codeHash) case 1 { - // The code oracle call can only fail in the case where the contract - // we are querying is the current one executing and it has not yet been - // deployed, i.e., if someone calls codesize (or extcodesize(address())) - // inside the constructor. In that case, code length is zero. - codeLen := 0 + // EraVM + let codeLengthInWords := and(shr(224, codeHash), 0xffff) + codeLen := shl(5, codeLengthInWords) // codeLengthInWords * 32 } - default { - // The first word is the true length of the bytecode - returndatacopy(0, 0, 32) - codeLen := mload(0) + case 2 { + // EVM + let codeLengthInBytes := and(shr(224, codeHash), 0xffff) + codeLen := codeLengthInBytes } - } function getDeployedBytecode() { @@ -397,32 +371,28 @@ object "EVMInterpreter" { function consumeEvmFrame() -> passGas, isStatic, callerEVM { // function consumeEvmFrame() external returns (uint256 passGas, bool isStatic) - // TODO: Unhardcode selector - mstore8(0, 0x04) - mstore8(1, 0xc1) - mstore8(2, 0x4e) - mstore8(3, 0x9e) + mstore(0, 0x04C14E9E00000000000000000000000000000000000000000000000000000000) let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 4, - gas(), - // Only rollup is supported for now - 0, - 0, - 0, - 1 - ) - let to := EVM_GAS_MANAGER_CONTRACT() - let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) + 0, + 0, + 0, + 4, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { // Should never happen revert(0, 0) } - + returndatacopy(0,0,64) passGas := mload(0) @@ -595,7 +565,7 @@ object "EVMInterpreter" { gasToCharge := 0 } } - + function checkMemOverflowByOffset(offset, evmGasLeft) { if gt(offset, MAX_POSSIBLE_MEM()) { mstore(0, evmGasLeft) @@ -668,11 +638,7 @@ object "EVMInterpreter" { } function isSlotWarm(key) -> isWarm { - // TODO: Unhardcode this selector 0x482d2e74 - mstore8(0, 0x48) - mstore8(1, 0x2d) - mstore8(2, 0x2e) - mstore8(3, 0x74) + mstore(0, 0x482D2E7400000000000000000000000000000000000000000000000000000000) mstore(4, key) let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) @@ -686,11 +652,7 @@ object "EVMInterpreter" { } function warmSlot(key,currentValue) -> isWarm, originalValue { - // TODO: Unhardcode this selector 0xbdf78160 - mstore8(0, 0xbd) - mstore8(1, 0xf7) - mstore8(2, 0x81) - mstore8(3, 0x60) + mstore(0, 0xBDF7816000000000000000000000000000000000000000000000000000000000) mstore(4, key) mstore(36,currentValue) @@ -713,7 +675,7 @@ object "EVMInterpreter" { // This error should never happen revert(0, 0) } - + returndatacopy(0, 0, 64) isWarm := mload(0) @@ -733,117 +695,50 @@ object "EVMInterpreter" { } } - function getNewAddress(addr) -> newAddr { - let digest, nonce, addressEncoded, nonceEncoded, nonceEncodedLength, listLength, listLengthEconded - - nonce := getNonce(addr) - - addressEncoded := and( - add(addr, shl(160, 0x94)), - 0xffffffffffffffffffffffffffffffffffffffffff - ) + function incrementNonce(addr) { + mstore(0, 0x306395C600000000000000000000000000000000000000000000000000000000) + mstore(4, addr) - nonceEncoded := nonce - nonceEncodedLength := 1 - if iszero(nonce) { - nonceEncoded := 128 - } - // The nonce has 4 bytes - if gt(nonce, 0xFFFFFF) { - nonceEncoded := shl(32, 0x84) - nonceEncoded := add(nonceEncoded, nonce) - nonceEncodedLength := 5 - } - // The nonce has 3 bytes - if and(gt(nonce, 0xFFFF), lt(nonce, 0x1000000)) { - nonceEncoded := shl(24, 0x83) - nonceEncoded := add(nonceEncoded, nonce) - nonceEncodedLength := 4 - } - // The nonce has 2 bytes - if and(gt(nonce, 0xFF), lt(nonce, 0x10000)) { - nonceEncoded := shl(16, 0x82) - nonceEncoded := add(nonceEncoded, nonce) - nonceEncodedLength := 3 - } - // The nonce has 1 byte and it's in [0x80, 0xFF] - if and(gt(nonce, 0x7F), lt(nonce, 0x100)) { - nonceEncoded := shl(8, 0x81) - nonceEncoded := add(nonceEncoded, nonce) - nonceEncodedLength := 2 - } - - listLength := add(21, nonceEncodedLength) - listLengthEconded := add(listLength, 0xC0) - - let arrayLength := add(168, mul(8, nonceEncodedLength)) - - digest := add( - shl(arrayLength, listLengthEconded), - add( - shl( - mul(8, nonceEncodedLength), - addressEncoded - ), - nonceEncoded - ) + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 36, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 ) + let to := NONCE_HOLDER_SYSTEM_CONTRACT() + let result := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - mstore(0, shl(sub(248, arrayLength), digest)) - - newAddr := and( - keccak256(0, add(div(arrayLength, 8), 1)), - 0xffffffffffffffffffffffffffffffffffffffff - ) - } - - function getFarCallABI( - dataOffset, - memoryPage, - dataStart, - dataLength, - gasPassed, - shardId, - forwardingMode, - isConstructorCall, - isSystemCall - ) -> ret { - let farCallAbi := 0 - farCallAbi := or(farCallAbi, dataOffset) - farCallAbi := or(farCallAbi, shl(64, dataStart)) - farCallAbi := or(farCallAbi, shl(96, dataLength)) - farCallAbi := or(farCallAbi, shl(192, gasPassed)) - farCallAbi := or(farCallAbi, shl(224, shardId)) - farCallAbi := or(farCallAbi, shl(232, forwardingMode)) - farCallAbi := or(farCallAbi, shl(248, 1)) - ret := farCallAbi + if iszero(result) { + revert(0, 0) } + } - function incrementNonce(addr) { - mstore8(0, 0x30) - mstore8(1, 0x63) - mstore8(2, 0x95) - mstore8(3, 0xc6) - mstore(4, addr) - - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 36, - gas(), - // Only rollup is supported for now - 0, - 0, - 0, - 1 - ) - let to := NONCE_HOLDER_SYSTEM_CONTRACT() - let result := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - - if iszero(result) { - revert(0, 0) - } + function getFarCallABI( + dataOffset, + memoryPage, + dataStart, + dataLength, + gasPassed, + shardId, + forwardingMode, + isConstructorCall, + isSystemCall + ) -> ret { + let farCallAbi := 0 + farCallAbi := or(farCallAbi, dataOffset) + farCallAbi := or(farCallAbi, shl(64, dataStart)) + farCallAbi := or(farCallAbi, shl(96, dataLength)) + farCallAbi := or(farCallAbi, shl(192, gasPassed)) + farCallAbi := or(farCallAbi, shl(224, shardId)) + farCallAbi := or(farCallAbi, shl(232, forwardingMode)) + farCallAbi := or(farCallAbi, shl(248, 1)) + ret := farCallAbi } function ensureAcceptableMemLocation(location) { @@ -868,11 +763,7 @@ object "EVMInterpreter" { } function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { - // TODO: Unhardcode this selector 0x8db2ba78 - mstore8(0, 0x8d) - mstore8(1, 0xb2) - mstore8(2, 0xba) - mstore8(3, 0x78) + mstore(0, 0x8DB2BA7800000000000000000000000000000000000000000000000000000000) mstore(4, addr) let farCallAbi := getFarCallABI( @@ -894,33 +785,13 @@ object "EVMInterpreter" { // This error should never happen revert(0, 0) } - - returndatacopy(0, 0, 32) + returndatacopy(0, 0, 32) isWarm := mload(0) } - - function getNonce(addr) -> nonce { - mstore8(0, 0xfb) - mstore8(1, 0x1a) - mstore8(2, 0x9a) - mstore8(3, 0x57) - mstore(4, addr) - - let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) - - if iszero(result) { - revert(0, 0) - } - nonce := mload(0) - } - function getRawNonce(addr) -> nonce { - mstore8(0, 0x5a) - mstore8(1, 0xa9) - mstore8(2, 0xb6) - mstore8(3, 0xb5) + mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) mstore(4, addr) let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) @@ -931,7 +802,7 @@ object "EVMInterpreter" { nonce := mload(0) } - + function _isEVM(_addr) -> isEVM { // bytes4 selector = ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM.selector; (0x8c040477) // function isAccountEVM(address _addr) external view returns (bool); @@ -939,10 +810,7 @@ object "EVMInterpreter" { // address(SYSTEM_CONTRACTS_OFFSET + 0x02) // ); - mstore8(0, 0x8c) - mstore8(1, 0x04) - mstore8(2, 0x04) - mstore8(3, 0x77) + mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) mstore(4, _addr) let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) @@ -954,15 +822,11 @@ object "EVMInterpreter" { isEVM := mload(0) } - + function _pushEVMFrame(_passGas, _isStatic) { // function pushEVMFrame(uint256 _passGas, bool _isStatic) external - let selector := 0xead77156 - mstore8(0, 0xea) - mstore8(1, 0xd7) - mstore8(2, 0x71) - mstore8(3, 0x56) + mstore(0, 0xEAD7715600000000000000000000000000000000000000000000000000000000) mstore(4, _passGas) mstore(36, _isStatic) @@ -978,21 +842,20 @@ object "EVMInterpreter" { 0, 1 ) - + let to := EVM_GAS_MANAGER_CONTRACT() let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - - // let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 0) + if iszero(success) { // This error should never happen revert(0, 0) } } - + function _popEVMFrame() { // function popEVMFrame() external - - let farCallAbi := getFarCallABI( + + let farCallAbi := getFarCallABI( 0, 0, 0, @@ -1004,16 +867,10 @@ object "EVMInterpreter" { 0, 1 ) - + let to := EVM_GAS_MANAGER_CONTRACT() - - // 0xe467d2f0 - let selector := 0xe467d2f0 - mstore8(0, 0xe4) - mstore8(1, 0x67) - mstore8(2, 0xd2) - mstore8(3, 0xf0) + mstore(0, 0xE467D2F000000000000000000000000000000000000000000000000000000000) let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { @@ -1023,7 +880,6 @@ object "EVMInterpreter" { } // Each evm gas is 5 zkEVM one - // FIXME: change this variable to reflect real ergs : gas ratio function GAS_DIVISOR() -> gas_div { gas_div := 5 } function EVM_GAS_STIPEND() -> gas_stipend { gas_stipend := shl(30, 1) } // 1 << 30 function OVERHEAD() -> overhead { overhead := 2000 } @@ -1121,11 +977,11 @@ object "EVMInterpreter" { addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - checkMultipleOverflow(argsOffset,argsSize,MEM_OFFSET_INNER(), evmGasLeft) - checkMultipleOverflow(retOffset, retSize,MEM_OFFSET_INNER(), evmGasLeft) + checkOverflow(argsOffset,argsSize, evmGasLeft) + checkOverflow(retOffset, retSize, evmGasLeft) - checkMemOverflow(add(add(argsOffset, argsSize), MEM_OFFSET_INNER()), evmGasLeft) - checkMemOverflow(add(add(retOffset, retSize), MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) extraCost := 0 if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -1143,18 +999,9 @@ object "EVMInterpreter" { let frameGasLeft let success - if _isEVM(addr) { - _pushEVMFrame(gasToPass, true) - // TODO Check the following comment from zkSync .sol. - // We can not just pass all gas here to prevent overflow of zkEVM gas counter - success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, 0, 0) - - frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - _popEVMFrame() - } - - // zkEVM native - if iszero(_isEVM(addr)) { + switch _isEVM(addr) + case 0 { + // zkEVM native gasToPass := _getZkEVMGas(gasToPass, addr) let zkevmGasBefore := gas() success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, add(MEM_OFFSET_INNER(), retOffset), retSize) @@ -1167,9 +1014,23 @@ object "EVMInterpreter" { frameGasLeft := sub(gasToPass, gasUsed) } } + default { + _pushEVMFrame(gasToPass, true) + success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, 0, 0) + + frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + _popEVMFrame() + } + + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch iszero(precompileCost) + case 1 { + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + } + default { + extraCost := add(extraCost, precompileCost) + } - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) - extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) sp := pushStackItem(sp, success, evmGasLeft) } function capGas(evmGasLeft,oldGasToPass) -> gasToPass { @@ -1194,7 +1055,31 @@ object "EVMInterpreter" { function _performCall(addr,gasToPass,value,argsOffset,argsSize,retOffset,retSize,isStatic) -> success, frameGasLeft, gasToPassNew{ gasToPassNew := gasToPass let is_evm := _isEVM(addr) - if isStatic { + + switch isStatic + case 0 { + switch is_evm + case 0 { + // zkEVM native + gasToPassNew := _getZkEVMGas(gasToPassNew, addr) + let zkevmGasBefore := gas() + success := call(gasToPassNew, addr, value, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + + frameGasLeft := 0 + if gt(gasToPassNew, gasUsed) { + frameGasLeft := sub(gasToPassNew, gasUsed) + } + } + default { + _pushEVMFrame(gasToPassNew, isStatic) + success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + _popEVMFrame() + } + } + default { if value { revertWithGas(gasToPassNew) } @@ -1208,27 +1093,6 @@ object "EVMInterpreter" { retSize ) } - - if and(is_evm, iszero(isStatic)) { - _pushEVMFrame(gasToPassNew, isStatic) - success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - _popEVMFrame() - } - - // zkEVM native - if and(iszero(is_evm), iszero(isStatic)) { - gasToPassNew := _getZkEVMGas(gasToPassNew, addr) - let zkevmGasBefore := gas() - success := call(gasToPassNew, addr, value, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) - - frameGasLeft := 0 - if gt(gasToPassNew, gasUsed) { - frameGasLeft := sub(gasToPassNew, gasUsed) - } - } } function performCall(oldSp, evmGasLeft, isStatic) -> extraCost, sp { @@ -1292,8 +1156,14 @@ object "EVMInterpreter" { isStatic ) - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) - extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch iszero(precompileCost) + case 1 { + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + } + default { + extraCost := add(extraCost, precompileCost) + } sp := pushStackItem(sp,success, evmGasLeft) } @@ -1311,13 +1181,13 @@ object "EVMInterpreter" { retOffset, sp := popStackItemWithoutCheck(sp) retSize, sp := popStackItemWithoutCheck(sp) - // addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - checkMultipleOverflow(argsOffset,argsSize,MEM_OFFSET_INNER(), evmGasLeft) - checkMultipleOverflow(retOffset, retSize,MEM_OFFSET_INNER(), evmGasLeft) + checkOverflow(argsOffset, argsSize, evmGasLeft) + checkOverflow(retOffset, retSize, evmGasLeft) - checkMemOverflow(add(add(argsOffset, argsSize), MEM_OFFSET_INNER()), evmGasLeft) - checkMemOverflow(add(add(retOffset, retSize), MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) if iszero(_isEVM(addr)) { revertWithGas(evmGasLeft) @@ -1334,13 +1204,6 @@ object "EVMInterpreter" { } gasToPass := capGas(evmGasLeft,gasToPass) - // TODO: Do this - // if warmAccount(addr) { - // extraCost = GAS_WARM_ACCESS; - // } else { - // extraCost = GAS_COLD_ACCOUNT_ACCESS; - // } - _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( // We can not just pass all gas here to prevent overflow of zkEVM gas counter @@ -1356,8 +1219,14 @@ object "EVMInterpreter" { _popEVMFrame() - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) - extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch iszero(precompileCost) + case 1 { + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + } + default { + extraCost := add(extraCost, precompileCost) + } sp := pushStackItem(sp, success, evmGasLeft) } @@ -1402,18 +1271,9 @@ object "EVMInterpreter" { _outputOffset, _outputLen ) -> success, _gasLeft { - if _calleeIsEVM { - _pushEVMFrame(_calleeGas, true) - // TODO Check the following comment from zkSync .sol. - // We can not just pass all gas here to prevent overflow of zkEVM gas counter - success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) - - _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) - _popEVMFrame() - } - - // zkEVM native - if iszero(_calleeIsEVM) { + switch _calleeIsEVM + case 0 { + // zkEVM native _calleeGas := _getZkEVMGas(_calleeGas, _callee) let zkevmGasBefore := gas() success := staticcall(_calleeGas, _callee, _inputOffset, _inputLen, _outputOffset, _outputLen) @@ -1427,6 +1287,13 @@ object "EVMInterpreter" { _gasLeft := sub(_calleeGas, gasUsed) } } + default { + _pushEVMFrame(_calleeGas, true) + success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) + + _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) + _popEVMFrame() + } } function isAddrEmpty(addr) -> isEmpty { @@ -1441,12 +1308,7 @@ object "EVMInterpreter" { } function _fetchConstructorReturnGas() -> gasLeft { - //selector is 0x24e5ab4a - - mstore8(0, 0x24) - mstore8(1, 0xe5) - mstore8(2, 0xab) - mstore8(3, 0x4a) + mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 32) @@ -1471,10 +1333,11 @@ object "EVMInterpreter" { offset := add(MEM_OFFSET_INNER(), offset) - sp := pushStackItem(sp, mload(sub(offset, 0x80)), evmGasLeftOld) - sp := pushStackItem(sp, mload(sub(offset, 0x60)), evmGasLeftOld) - sp := pushStackItem(sp, mload(sub(offset, 0x40)), evmGasLeftOld) - sp := pushStackItem(sp, mload(sub(offset, 0x20)), evmGasLeftOld) + pushStackCheck(sp, evmGasLeftOld, 4) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80))) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60))) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40))) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20))) _pushEVMFrame(gasForTheCall, false) @@ -1487,12 +1350,12 @@ object "EVMInterpreter" { mstore(sub(offset, 0x40), 0x40) // Length of the init code mstore(sub(offset, 0x20), size) - - + + result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) } - - + + if iszero(isCreate2) { // CreateEVM selector mstore(sub(offset, 0x60), 0xff311601) @@ -1500,11 +1363,11 @@ object "EVMInterpreter" { mstore(sub(offset, 0x40), 0x20) // Length of the init code mstore(sub(offset, 0x20), size) - - + + result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) } - + addr := mload(0) let gasLeft @@ -1515,7 +1378,7 @@ object "EVMInterpreter" { default { gasLeft := _fetchConstructorReturnGas() } - + let gasUsed := sub(gasForTheCall, gasLeft) evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) @@ -1523,7 +1386,7 @@ object "EVMInterpreter" { let back - popStackCheck(sp, evmGasLeft, 4) + // skipping check since we pushed exactly 4 items earlier back, sp := popStackItemWithoutCheck(sp) mstore(sub(offset, 0x20), back) back, sp := popStackItemWithoutCheck(sp) @@ -1534,6 +1397,45 @@ object "EVMInterpreter" { mstore(sub(offset, 0x80), back) } + function $llvm_AlwaysInline_llvm$_copyRest(dest, val, len) { + let rest_bits := shl(3, len) + let upper_bits := sub(256, rest_bits) + let val_mask := shl(upper_bits, MAX_UINT()) + let val_masked := and(val, val_mask) + let dst_val := mload(dest) + let dst_mask := shr(rest_bits, MAX_UINT()) + let dst_masked := and(dst_val, dst_mask) + mstore(dest, or(val_masked, dst_masked)) + } + + function $llvm_AlwaysInline_llvm$_memcpy(dest, src, len) { + let dest_addr := dest + let src_addr := src + let dest_end := add(dest, and(len, sub(0, 32))) + for { } lt(dest_addr, dest_end) {} { + mstore(dest_addr, mload(src_addr)) + dest_addr := add(dest_addr, 32) + src_addr := add(src_addr, 32) + } + + let rest_len := and(len, 31) + if rest_len { + $llvm_AlwaysInline_llvm$_copyRest(dest_addr, mload(src_addr), rest_len) + } + } + + function $llvm_AlwaysInline_llvm$_memsetToZero(dest,len) { + let dest_end := add(dest, and(len, sub(0, 32))) + for {let i := dest} lt(i, dest_end) { i := add(i, 32) } { + mstore(i, 0) + } + + let rest_len := and(len, 31) + if rest_len { + $llvm_AlwaysInline_llvm$_copyRest(dest_end, 0, rest_len) + } + } + function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { evmGasLeft := chargeGas(evmGas, 100) @@ -1556,21 +1458,12 @@ object "EVMInterpreter" { } evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - let len_32 := shr(5, len) - for {let i := 0} lt(i, len_32) { i := add(i, 1) } { - mstore(add(dest,shl(5,i)),0) - } - let size_32 := shl(5,len_32) - let rest_32 := sub(len, size_32) - for {let i := 0} lt(i, rest_32) { i := add(i, 1) } { - mstore8(add(dest,add(size_32,i)),0) - } + $llvm_AlwaysInline_llvm$_memsetToZero(dest, len) // Gets the code from the addr - if iszero(iszero(_getRawCodeHash(addr))) { + if and(iszero(iszero(_getRawCodeHash(addr))),gt(len,0)) { pop(_fetchDeployedCodeWithDest(addr, offset, len,add(dest,MEM_OFFSET_INNER()))) } - } function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { @@ -1587,9 +1480,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) - - checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { revertWithGas(evmGasLeft) @@ -1610,7 +1502,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) let result, addr - result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,false,0) + result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0) switch result case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } @@ -1632,9 +1524,8 @@ object "EVMInterpreter" { size, sp := popStackItemWithoutCheck(sp) salt, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) - - checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { revertWithGas(evmGasLeft) @@ -1654,20 +1545,7 @@ object "EVMInterpreter" { shr(2, add(size, 31)) )) - { - let hashedBytecode := keccak256(add(MEM_OFFSET_INNER(), offset), size) - mstore8(0, 0xFF) - mstore(0x01, shl(0x60, address())) - mstore(0x15, salt) - mstore(0x35, hashedBytecode) - } - - addr := and( - keccak256(0, 0x55), - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - ) - - result, evmGasLeft := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, true, salt) + result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt) } @@ -1701,7 +1579,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1713,7 +1591,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1725,7 +1603,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1737,7 +1615,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1749,7 +1627,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1761,7 +1639,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1773,7 +1651,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1785,7 +1663,7 @@ object "EVMInterpreter" { let a, b, N - popPushStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, evmGasLeft, 3) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) N, sp := popStackItemWithoutCheck(sp) @@ -1811,7 +1689,7 @@ object "EVMInterpreter" { let a, exponent - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) exponent, sp := popStackItemWithoutCheck(sp) @@ -1830,7 +1708,7 @@ object "EVMInterpreter" { let b, x - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) b, sp := popStackItemWithoutCheck(sp) x, sp := popStackItemWithoutCheck(sp) @@ -1842,7 +1720,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1854,7 +1732,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1866,7 +1744,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1878,7 +1756,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1890,7 +1768,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1902,7 +1780,7 @@ object "EVMInterpreter" { let a - popPushStackCheck(sp, evmGasLeft, 1) + popStackCheck(sp, evmGasLeft, 1) a, sp := popStackItemWithoutCheck(sp) sp := pushStackItemWithoutCheck(sp, iszero(a)) @@ -1913,7 +1791,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1925,7 +1803,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1937,7 +1815,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -1949,7 +1827,7 @@ object "EVMInterpreter" { let a - popPushStackCheck(sp, evmGasLeft, 1) + popStackCheck(sp, evmGasLeft, 1) a, sp := popStackItemWithoutCheck(sp) sp := pushStackItemWithoutCheck(sp, not(a)) @@ -1960,7 +1838,7 @@ object "EVMInterpreter" { let i, x - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) i, sp := popStackItemWithoutCheck(sp) x, sp := popStackItemWithoutCheck(sp) @@ -1972,7 +1850,7 @@ object "EVMInterpreter" { let shift, value - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) shift, sp := popStackItemWithoutCheck(sp) value, sp := popStackItemWithoutCheck(sp) @@ -1984,7 +1862,7 @@ object "EVMInterpreter" { let shift, value - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) shift, sp := popStackItemWithoutCheck(sp) value, sp := popStackItemWithoutCheck(sp) @@ -1996,7 +1874,7 @@ object "EVMInterpreter" { let shift, value - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) shift, sp := popStackItemWithoutCheck(sp) value, sp := popStackItemWithoutCheck(sp) @@ -2012,8 +1890,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) - checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) let keccak := keccak256(add(MEM_OFFSET_INNER(), offset), size) // When an offset is first accessed (either read or write), memory may trigger @@ -2044,7 +1922,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItem(sp, balance(addr), evmGasLeft) + sp := pushStackItemWithoutCheck(sp, balance(addr)) ip := add(ip, 1) } case 0x32 { // OP_ORIGIN @@ -2070,7 +1948,7 @@ object "EVMInterpreter" { let i - popPushStackCheck(sp, evmGasLeft, 1) + popStackCheck(sp, evmGasLeft, 1) i, sp := popStackItemWithoutCheck(sp) sp := pushStackItemWithoutCheck(sp, calldataload(i)) @@ -2095,13 +1973,9 @@ object "EVMInterpreter" { checkMultipleOverflow(offset,size,MEM_OFFSET_INNER(), evmGasLeft) checkMultipleOverflow(destOffset,size,MEM_OFFSET_INNER(), evmGasLeft) + // TODO invalid? if or(gt(add(add(offset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM()), gt(add(add(destOffset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM())) { - for { let i := 0 } lt(i, size) { i := add(i, 1) } { - mstore8( - add(add(destOffset, MEM_OFFSET_INNER()), i), - 0 - ) - } + $llvm_AlwaysInline_llvm$_memsetToZero(add(destOffset, MEM_OFFSET_INNER()), size) } // dynamicGas = 3 * minimum_word_size + memory_expansion_cost @@ -2146,12 +2020,7 @@ object "EVMInterpreter" { revertWithGas(evmGasLeft) } - for { let i := 0 } lt(i, len) { i := add(i, 1) } { - mstore8( - add(dst, i), - shr(248, mload(add(offset, i))) - ) - } + $llvm_AlwaysInline_llvm$_memcpy(dst, offset, len) ip := add(ip, 1) } case 0x3A { // OP_GASPRICE @@ -2171,14 +2040,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - // TODO: check, the .sol uses extcodesize directly, but it doesn't seem to work - // if a contract is created it works, but if the address is a zkSync's contract - // what happens? - // sp := pushStackItem(sp, extcodesize(addr), evmGasLeft) - - switch _isEVM(addr) - case 0 { sp := pushStackItem(sp, extcodesize(addr), evmGasLeft) } - default { sp := pushStackItem(sp, _fetchDeployedCodeLen(addr), evmGasLeft) } + sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY @@ -2201,9 +2063,6 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) len, sp := popStackItemWithoutCheck(sp) - // TODO: check if these conditions are met - // The addition offset + size overflows. - // offset + size is larger than RETURNDATASIZE. checkOverflow(offset,len, evmGasLeft) if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { revertWithGas(evmGasLeft) @@ -2211,7 +2070,7 @@ object "EVMInterpreter" { // minimum_word_size = (size + 31) / 32 // dynamicGas = 3 * minimum_word_size + memory_expansion_cost - checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(offset, evmGasLeft) let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dest, len))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -2231,16 +2090,16 @@ object "EVMInterpreter" { ip := add(ip, 1) if iszero(addr) { - sp := pushStackItem(sp, 0, evmGasLeft) + sp := pushStackItemWithoutCheck(sp, 0) continue } - sp := pushStackItem(sp, extcodehash(addr), evmGasLeft) + sp := pushStackItemWithoutCheck(sp, extcodehash(addr)) } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) let blockNumber - popPushStackCheck(sp, evmGasLeft, 1) + popStackCheck(sp, evmGasLeft, 1) blockNumber, sp := popStackItemWithoutCheck(sp) sp := pushStackItemWithoutCheck(sp, blockhash(blockNumber)) @@ -2301,13 +2160,12 @@ object "EVMInterpreter" { offset, sp := popStackItem(sp, evmGasLeft) - checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) let memValue := mload(add(MEM_OFFSET_INNER(), offset)) - sp := pushStackItem(sp, memValue, evmGasLeft) + sp := pushStackItemWithoutCheck(sp, memValue) ip := add(ip, 1) } case 0x52 { // OP_MSTORE @@ -2319,11 +2177,10 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) value, sp := popStackItemWithoutCheck(sp) - checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) mstore(add(MEM_OFFSET_INNER(), offset), value) ip := add(ip, 1) } @@ -2336,11 +2193,10 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) value, sp := popStackItemWithoutCheck(sp) - checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 1)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) mstore8(add(MEM_OFFSET_INNER(), offset), value) ip := add(ip, 1) } @@ -2364,7 +2220,7 @@ object "EVMInterpreter" { let _wasW, _orgV := warmSlot(key, value) } - sp := pushStackItem(sp,value, evmGasLeft) + sp := pushStackItemWithoutCheck(sp,value) ip := add(ip, 1) } case 0x55 { // OP_SSTORE @@ -2424,6 +2280,10 @@ object "EVMInterpreter" { if iszero(eq(nextOpcode, 0x5B)) { revertWithGas(evmGasLeft) } + + // execute JUMPDEST immediately + evmGasLeft := chargeGas(evmGasLeft, 1) + ip := add(ip, 1) } case 0x57 { // OP_JUMPI evmGasLeft := chargeGas(evmGasLeft, 10) @@ -2446,6 +2306,10 @@ object "EVMInterpreter" { if iszero(eq(nextOpcode, 0x5B)) { revertWithGas(evmGasLeft) } + + // execute JUMPDEST immediately + evmGasLeft := chargeGas(evmGasLeft, 1) + ip := add(ip, 1) } case 0x58 { // OP_PC evmGasLeft := chargeGas(evmGasLeft, 2) @@ -2478,7 +2342,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 100) let key - popPushStackCheck(sp, evmGasLeft, 1) + popStackCheck(sp, evmGasLeft, 1) key, sp := popStackItemWithoutCheck(sp) sp := pushStackItemWithoutCheck(sp, tload(key)) @@ -2506,26 +2370,14 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) + // TODO overflow checks + checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemOverflowByOffset(add(destOffset, size), evmGasLeft) + expandMemory(add(destOffset, size)) expandMemory(add(offset, size)) - let oldSize := mul(mload(MEM_OFFSET()),32) - if gt(add(oldSize,size),MAX_POSSIBLE_MEM()) { - revertWithGas(evmGasLeft) - } - - for { let i := 0 } lt(i, size) { i := add(i, 1) } { - mstore8( - add(add(oldSize,MEM_OFFSET_INNER()), i), - shr(248,mload(add(add(offset,MEM_OFFSET_INNER()), i))) - ) - } - for { let i := 0 } lt(i, size) { i := add(i, 1) } { - mstore8( - add(add(destOffset,MEM_OFFSET_INNER()), i), - shr(248,mload(add(add(oldSize,MEM_OFFSET_INNER()), i))) - ) - } + mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) ip := add(ip, 1) } case 0x5F { // OP_PUSH0 @@ -2964,8 +2816,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) - checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -2987,8 +2839,8 @@ object "EVMInterpreter" { size, sp := popStackItemWithoutCheck(sp) topic1, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) - checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -3009,8 +2861,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) - checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -3038,9 +2890,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) - - checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -3069,8 +2920,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) - checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -3151,6 +3002,7 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) + // TODO invalid? ensureAcceptableMemLocation(offset) ensureAcceptableMemLocation(size) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) @@ -3280,7 +3132,6 @@ object "EVMInterpreter" { // It is the responsibility of the caller to ensure that ip >= BYTECODE_OFFSET + 32 function readIP(ip,maxAcceptablePos) -> opcode { - // TODO: Why not do this at the beginning once instead of every time? if gt(ip, maxAcceptablePos) { revert(0, 0) } @@ -3368,11 +3219,8 @@ object "EVMInterpreter" { } } - function popPushStackCheck(sp, evmGasLeft, numInputs) { - let popCheck := lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) - let pushOffset := sub(sp, mul(0x20, numInputs)) - let pushCheck := or(gt(pushOffset, BYTECODE_OFFSET()), eq(pushOffset, BYTECODE_OFFSET())) - if or(popCheck, pushCheck) { + function pushStackCheck(sp, evmGasLeft, numInputs) { + if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { revertWithGas(evmGasLeft) } } @@ -3406,11 +3254,7 @@ object "EVMInterpreter" { } function _getRawCodeHash(account) -> hash { - // TODO: Unhardcode this selector - mstore8(0, 0x4d) - mstore8(1, 0xe2) - mstore8(2, 0xe4) - mstore8(3, 0x68) + mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) @@ -3425,12 +3269,7 @@ object "EVMInterpreter" { function _getCodeHash(account) -> hash { // function getCodeHash(uint256 _input) external view override returns (bytes32) - // 0xe03fe177 - // TODO: Unhardcode this selector - mstore8(0, 0xe0) - mstore8(1, 0x3f) - mstore8(2, 0xe1) - mstore8(3, 0x77) + mstore(0, 0xE03FE17700000000000000000000000000000000000000000000000000000000) mstore(4, account) let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) @@ -3445,7 +3284,6 @@ object "EVMInterpreter" { function getIsStaticFromCallFlags() -> isStatic { isStatic := verbatim_0i_1o("get_global::call_flags") - // TODO: make it a constnat isStatic := iszero(iszero(and(isStatic, 0x04))) } @@ -3482,24 +3320,17 @@ object "EVMInterpreter" { function _fetchDeployedCodeLen(addr) -> codeLen { let codeHash := _getRawCodeHash(addr) - mstore(0, codeHash) - - let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) - - switch iszero(success) + switch shr(248, codeHash) case 1 { - // The code oracle call can only fail in the case where the contract - // we are querying is the current one executing and it has not yet been - // deployed, i.e., if someone calls codesize (or extcodesize(address())) - // inside the constructor. In that case, code length is zero. - codeLen := 0 + // EraVM + let codeLengthInWords := and(shr(224, codeHash), 0xffff) + codeLen := shl(5, codeLengthInWords) // codeLengthInWords * 32 } - default { - // The first word is the true length of the bytecode - returndatacopy(0, 0, 32) - codeLen := mload(0) + case 2 { + // EVM + let codeLengthInBytes := and(shr(224, codeHash), 0xffff) + codeLen := codeLengthInBytes } - } function getDeployedBytecode() { @@ -3514,11 +3345,7 @@ object "EVMInterpreter" { function consumeEvmFrame() -> passGas, isStatic, callerEVM { // function consumeEvmFrame() external returns (uint256 passGas, bool isStatic) - // TODO: Unhardcode selector - mstore8(0, 0x04) - mstore8(1, 0xc1) - mstore8(2, 0x4e) - mstore8(3, 0x9e) + mstore(0, 0x04C14E9E00000000000000000000000000000000000000000000000000000000) let farCallAbi := getFarCallABI( 0, @@ -3539,9 +3366,9 @@ object "EVMInterpreter" { // Should never happen revert(0, 0) } - + returndatacopy(0,0,64) - + passGas := mload(0) isStatic := mload(32) @@ -3712,7 +3539,7 @@ object "EVMInterpreter" { gasToCharge := 0 } } - + function checkMemOverflowByOffset(offset, evmGasLeft) { if gt(offset, MAX_POSSIBLE_MEM()) { mstore(0, evmGasLeft) @@ -3785,11 +3612,7 @@ object "EVMInterpreter" { } function isSlotWarm(key) -> isWarm { - // TODO: Unhardcode this selector 0x482d2e74 - mstore8(0, 0x48) - mstore8(1, 0x2d) - mstore8(2, 0x2e) - mstore8(3, 0x74) + mstore(0, 0x482D2E7400000000000000000000000000000000000000000000000000000000) mstore(4, key) let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) @@ -3803,11 +3626,7 @@ object "EVMInterpreter" { } function warmSlot(key,currentValue) -> isWarm, originalValue { - // TODO: Unhardcode this selector 0xbdf78160 - mstore8(0, 0xbd) - mstore8(1, 0xf7) - mstore8(2, 0x81) - mstore8(3, 0x60) + mstore(0, 0xBDF7816000000000000000000000000000000000000000000000000000000000) mstore(4, key) mstore(36,currentValue) @@ -3830,7 +3649,7 @@ object "EVMInterpreter" { // This error should never happen revert(0, 0) } - + returndatacopy(0, 0, 64) isWarm := mload(0) @@ -3850,71 +3669,31 @@ object "EVMInterpreter" { } } - function getNewAddress(addr) -> newAddr { - let digest, nonce, addressEncoded, nonceEncoded, nonceEncodedLength, listLength, listLengthEconded - - nonce := getNonce(addr) - - addressEncoded := and( - add(addr, shl(160, 0x94)), - 0xffffffffffffffffffffffffffffffffffffffffff - ) + function incrementNonce(addr) { + mstore(0, 0x306395C600000000000000000000000000000000000000000000000000000000) + mstore(4, addr) - nonceEncoded := nonce - nonceEncodedLength := 1 - if iszero(nonce) { - nonceEncoded := 128 - } - // The nonce has 4 bytes - if gt(nonce, 0xFFFFFF) { - nonceEncoded := shl(32, 0x84) - nonceEncoded := add(nonceEncoded, nonce) - nonceEncodedLength := 5 - } - // The nonce has 3 bytes - if and(gt(nonce, 0xFFFF), lt(nonce, 0x1000000)) { - nonceEncoded := shl(24, 0x83) - nonceEncoded := add(nonceEncoded, nonce) - nonceEncodedLength := 4 - } - // The nonce has 2 bytes - if and(gt(nonce, 0xFF), lt(nonce, 0x10000)) { - nonceEncoded := shl(16, 0x82) - nonceEncoded := add(nonceEncoded, nonce) - nonceEncodedLength := 3 - } - // The nonce has 1 byte and it's in [0x80, 0xFF] - if and(gt(nonce, 0x7F), lt(nonce, 0x100)) { - nonceEncoded := shl(8, 0x81) - nonceEncoded := add(nonceEncoded, nonce) - nonceEncodedLength := 2 - } - - listLength := add(21, nonceEncodedLength) - listLengthEconded := add(listLength, 0xC0) - - let arrayLength := add(168, mul(8, nonceEncodedLength)) - - digest := add( - shl(arrayLength, listLengthEconded), - add( - shl( - mul(8, nonceEncodedLength), - addressEncoded - ), - nonceEncoded - ) + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 36, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 ) + let to := NONCE_HOLDER_SYSTEM_CONTRACT() + let result := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - mstore(0, shl(sub(248, arrayLength), digest)) + if iszero(result) { + revert(0, 0) + } + } - newAddr := and( - keccak256(0, add(div(arrayLength, 8), 1)), - 0xffffffffffffffffffffffffffffffffffffffff - ) - } - - function getFarCallABI( + function getFarCallABI( dataOffset, memoryPage, dataStart, @@ -3936,33 +3715,6 @@ object "EVMInterpreter" { ret := farCallAbi } - function incrementNonce(addr) { - mstore8(0, 0x30) - mstore8(1, 0x63) - mstore8(2, 0x95) - mstore8(3, 0xc6) - mstore(4, addr) - - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 36, - gas(), - // Only rollup is supported for now - 0, - 0, - 0, - 1 - ) - let to := NONCE_HOLDER_SYSTEM_CONTRACT() - let result := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - - if iszero(result) { - revert(0, 0) - } - } - function ensureAcceptableMemLocation(location) { if gt(location,MAX_POSSIBLE_MEM()) { revert(0,0) // Check if this is what's needed @@ -3985,11 +3737,7 @@ object "EVMInterpreter" { } function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { - // TODO: Unhardcode this selector 0x8db2ba78 - mstore8(0, 0x8d) - mstore8(1, 0xb2) - mstore8(2, 0xba) - mstore8(3, 0x78) + mstore(0, 0x8DB2BA7800000000000000000000000000000000000000000000000000000000) mstore(4, addr) let farCallAbi := getFarCallABI( @@ -4001,43 +3749,23 @@ object "EVMInterpreter" { // Only rollup is supported for now 0, 0, - 0, - 1 - ) - let to := EVM_GAS_MANAGER_CONTRACT() - let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - returndatacopy(0, 0, 32) - - isWarm := mload(0) - } - - function getNonce(addr) -> nonce { - mstore8(0, 0xfb) - mstore8(1, 0x1a) - mstore8(2, 0x9a) - mstore8(3, 0x57) - mstore(4, addr) - - let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) + 0, + 1 + ) + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - if iszero(result) { + if iszero(success) { + // This error should never happen revert(0, 0) } - nonce := mload(0) + returndatacopy(0, 0, 32) + isWarm := mload(0) } function getRawNonce(addr) -> nonce { - mstore8(0, 0x5a) - mstore8(1, 0xa9) - mstore8(2, 0xb6) - mstore8(3, 0xb5) + mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) mstore(4, addr) let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) @@ -4056,10 +3784,7 @@ object "EVMInterpreter" { // address(SYSTEM_CONTRACTS_OFFSET + 0x02) // ); - mstore8(0, 0x8c) - mstore8(1, 0x04) - mstore8(2, 0x04) - mstore8(3, 0x77) + mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) mstore(4, _addr) let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) @@ -4074,12 +3799,8 @@ object "EVMInterpreter" { function _pushEVMFrame(_passGas, _isStatic) { // function pushEVMFrame(uint256 _passGas, bool _isStatic) external - let selector := 0xead77156 - mstore8(0, 0xea) - mstore8(1, 0xd7) - mstore8(2, 0x71) - mstore8(3, 0x56) + mstore(0, 0xEAD7715600000000000000000000000000000000000000000000000000000000) mstore(4, _passGas) mstore(36, _isStatic) @@ -4095,11 +3816,10 @@ object "EVMInterpreter" { 0, 1 ) - + let to := EVM_GAS_MANAGER_CONTRACT() let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - - // let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 68, 0, 0) + if iszero(success) { // This error should never happen revert(0, 0) @@ -4108,8 +3828,8 @@ object "EVMInterpreter" { function _popEVMFrame() { // function popEVMFrame() external - - let farCallAbi := getFarCallABI( + + let farCallAbi := getFarCallABI( 0, 0, 0, @@ -4121,16 +3841,10 @@ object "EVMInterpreter" { 0, 1 ) - + let to := EVM_GAS_MANAGER_CONTRACT() - - // 0xe467d2f0 - let selector := 0xe467d2f0 - mstore8(0, 0xe4) - mstore8(1, 0x67) - mstore8(2, 0xd2) - mstore8(3, 0xf0) + mstore(0, 0xE467D2F000000000000000000000000000000000000000000000000000000000) let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) if iszero(success) { @@ -4140,7 +3854,6 @@ object "EVMInterpreter" { } // Each evm gas is 5 zkEVM one - // FIXME: change this variable to reflect real ergs : gas ratio function GAS_DIVISOR() -> gas_div { gas_div := 5 } function EVM_GAS_STIPEND() -> gas_stipend { gas_stipend := shl(30, 1) } // 1 << 30 function OVERHEAD() -> overhead { overhead := 2000 } @@ -4238,11 +3951,11 @@ object "EVMInterpreter" { addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - checkMultipleOverflow(argsOffset,argsSize,MEM_OFFSET_INNER(), evmGasLeft) - checkMultipleOverflow(retOffset, retSize,MEM_OFFSET_INNER(), evmGasLeft) + checkOverflow(argsOffset,argsSize, evmGasLeft) + checkOverflow(retOffset, retSize, evmGasLeft) - checkMemOverflow(add(add(argsOffset, argsSize), MEM_OFFSET_INNER()), evmGasLeft) - checkMemOverflow(add(add(retOffset, retSize), MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) extraCost := 0 if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -4260,18 +3973,9 @@ object "EVMInterpreter" { let frameGasLeft let success - if _isEVM(addr) { - _pushEVMFrame(gasToPass, true) - // TODO Check the following comment from zkSync .sol. - // We can not just pass all gas here to prevent overflow of zkEVM gas counter - success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, 0, 0) - - frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - _popEVMFrame() - } - - // zkEVM native - if iszero(_isEVM(addr)) { + switch _isEVM(addr) + case 0 { + // zkEVM native gasToPass := _getZkEVMGas(gasToPass, addr) let zkevmGasBefore := gas() success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, add(MEM_OFFSET_INNER(), retOffset), retSize) @@ -4284,9 +3988,23 @@ object "EVMInterpreter" { frameGasLeft := sub(gasToPass, gasUsed) } } + default { + _pushEVMFrame(gasToPass, true) + success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, 0, 0) + + frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + _popEVMFrame() + } + + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch iszero(precompileCost) + case 1 { + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + } + default { + extraCost := add(extraCost, precompileCost) + } - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) - extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) sp := pushStackItem(sp, success, evmGasLeft) } function capGas(evmGasLeft,oldGasToPass) -> gasToPass { @@ -4311,7 +4029,31 @@ object "EVMInterpreter" { function _performCall(addr,gasToPass,value,argsOffset,argsSize,retOffset,retSize,isStatic) -> success, frameGasLeft, gasToPassNew{ gasToPassNew := gasToPass let is_evm := _isEVM(addr) - if isStatic { + + switch isStatic + case 0 { + switch is_evm + case 0 { + // zkEVM native + gasToPassNew := _getZkEVMGas(gasToPassNew, addr) + let zkevmGasBefore := gas() + success := call(gasToPassNew, addr, value, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + + frameGasLeft := 0 + if gt(gasToPassNew, gasUsed) { + frameGasLeft := sub(gasToPassNew, gasUsed) + } + } + default { + _pushEVMFrame(gasToPassNew, isStatic) + success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + _popEVMFrame() + } + } + default { if value { revertWithGas(gasToPassNew) } @@ -4325,27 +4067,6 @@ object "EVMInterpreter" { retSize ) } - - if and(is_evm, iszero(isStatic)) { - _pushEVMFrame(gasToPassNew, isStatic) - success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - _popEVMFrame() - } - - // zkEVM native - if and(iszero(is_evm), iszero(isStatic)) { - gasToPassNew := _getZkEVMGas(gasToPassNew, addr) - let zkevmGasBefore := gas() - success := call(gasToPassNew, addr, value, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) - - frameGasLeft := 0 - if gt(gasToPassNew, gasUsed) { - frameGasLeft := sub(gasToPassNew, gasUsed) - } - } } function performCall(oldSp, evmGasLeft, isStatic) -> extraCost, sp { @@ -4409,8 +4130,14 @@ object "EVMInterpreter" { isStatic ) - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) - extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch iszero(precompileCost) + case 1 { + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + } + default { + extraCost := add(extraCost, precompileCost) + } sp := pushStackItem(sp,success, evmGasLeft) } @@ -4428,13 +4155,13 @@ object "EVMInterpreter" { retOffset, sp := popStackItemWithoutCheck(sp) retSize, sp := popStackItemWithoutCheck(sp) - // addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - checkMultipleOverflow(argsOffset,argsSize,MEM_OFFSET_INNER(), evmGasLeft) - checkMultipleOverflow(retOffset, retSize,MEM_OFFSET_INNER(), evmGasLeft) + checkOverflow(argsOffset, argsSize, evmGasLeft) + checkOverflow(retOffset, retSize, evmGasLeft) - checkMemOverflow(add(add(argsOffset, argsSize), MEM_OFFSET_INNER()), evmGasLeft) - checkMemOverflow(add(add(retOffset, retSize), MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) if iszero(_isEVM(addr)) { revertWithGas(evmGasLeft) @@ -4451,13 +4178,6 @@ object "EVMInterpreter" { } gasToPass := capGas(evmGasLeft,gasToPass) - // TODO: Do this - // if warmAccount(addr) { - // extraCost = GAS_WARM_ACCESS; - // } else { - // extraCost = GAS_COLD_ACCOUNT_ACCESS; - // } - _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( // We can not just pass all gas here to prevent overflow of zkEVM gas counter @@ -4473,8 +4193,14 @@ object "EVMInterpreter" { _popEVMFrame() - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) - extraCost := add(extraCost, getGasForPrecompiles(addr, argsOffset, argsSize)) + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch iszero(precompileCost) + case 1 { + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + } + default { + extraCost := add(extraCost, precompileCost) + } sp := pushStackItem(sp, success, evmGasLeft) } @@ -4519,18 +4245,9 @@ object "EVMInterpreter" { _outputOffset, _outputLen ) -> success, _gasLeft { - if _calleeIsEVM { - _pushEVMFrame(_calleeGas, true) - // TODO Check the following comment from zkSync .sol. - // We can not just pass all gas here to prevent overflow of zkEVM gas counter - success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) - - _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) - _popEVMFrame() - } - - // zkEVM native - if iszero(_calleeIsEVM) { + switch _calleeIsEVM + case 0 { + // zkEVM native _calleeGas := _getZkEVMGas(_calleeGas, _callee) let zkevmGasBefore := gas() success := staticcall(_calleeGas, _callee, _inputOffset, _inputLen, _outputOffset, _outputLen) @@ -4544,6 +4261,13 @@ object "EVMInterpreter" { _gasLeft := sub(_calleeGas, gasUsed) } } + default { + _pushEVMFrame(_calleeGas, true) + success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) + + _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) + _popEVMFrame() + } } function isAddrEmpty(addr) -> isEmpty { @@ -4558,12 +4282,7 @@ object "EVMInterpreter" { } function _fetchConstructorReturnGas() -> gasLeft { - //selector is 0x24e5ab4a - - mstore8(0, 0x24) - mstore8(1, 0xe5) - mstore8(2, 0xab) - mstore8(3, 0x4a) + mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 32) @@ -4576,80 +4295,120 @@ object "EVMInterpreter" { } function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt) -> result, evmGasLeft, addr { - pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) - - _eraseReturndataPointer() - - let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) - - if lt(selfbalance(),value) { - revertWithGas(evmGasLeftOld) + pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) + + _eraseReturndataPointer() + + let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) + + if lt(selfbalance(),value) { + revertWithGas(evmGasLeftOld) + } + + offset := add(MEM_OFFSET_INNER(), offset) + + pushStackCheck(sp, evmGasLeftOld, 4) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80))) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60))) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40))) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20))) + + _pushEVMFrame(gasForTheCall, false) + + if isCreate2 { + // Create2EVM selector + mstore(sub(offset, 0x80), 0x4e96f4c0) + // salt + mstore(sub(offset, 0x60), salt) + // Where the arg starts (third word) + mstore(sub(offset, 0x40), 0x40) + // Length of the init code + mstore(sub(offset, 0x20), size) + + + result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) + } + + + if iszero(isCreate2) { + // CreateEVM selector + mstore(sub(offset, 0x60), 0xff311601) + // Where the arg starts (second word) + mstore(sub(offset, 0x40), 0x20) + // Length of the init code + mstore(sub(offset, 0x20), size) + + + result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) + } + + addr := mload(0) + + let gasLeft + switch result + case 0 { + gasLeft := _saveReturndataAfterEVMCall(0, 0) + } + default { + gasLeft := _fetchConstructorReturnGas() + } + + let gasUsed := sub(gasForTheCall, gasLeft) + evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) + + _popEVMFrame() + + let back + + // skipping check since we pushed exactly 4 items earlier + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x20), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x40), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x60), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x80), back) } - - offset := add(MEM_OFFSET_INNER(), offset) - - sp := pushStackItem(sp, mload(sub(offset, 0x80)), evmGasLeftOld) - sp := pushStackItem(sp, mload(sub(offset, 0x60)), evmGasLeftOld) - sp := pushStackItem(sp, mload(sub(offset, 0x40)), evmGasLeftOld) - sp := pushStackItem(sp, mload(sub(offset, 0x20)), evmGasLeftOld) - - _pushEVMFrame(gasForTheCall, false) - - if isCreate2 { - // Create2EVM selector - mstore(sub(offset, 0x80), 0x4e96f4c0) - // salt - mstore(sub(offset, 0x60), salt) - // Where the arg starts (third word) - mstore(sub(offset, 0x40), 0x40) - // Length of the init code - mstore(sub(offset, 0x20), size) - - - result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) + + function $llvm_AlwaysInline_llvm$_copyRest(dest, val, len) { + let rest_bits := shl(3, len) + let upper_bits := sub(256, rest_bits) + let val_mask := shl(upper_bits, MAX_UINT()) + let val_masked := and(val, val_mask) + let dst_val := mload(dest) + let dst_mask := shr(rest_bits, MAX_UINT()) + let dst_masked := and(dst_val, dst_mask) + mstore(dest, or(val_masked, dst_masked)) } - - - if iszero(isCreate2) { - // CreateEVM selector - mstore(sub(offset, 0x60), 0xff311601) - // Where the arg starts (second word) - mstore(sub(offset, 0x40), 0x20) - // Length of the init code - mstore(sub(offset, 0x20), size) - - - result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) + + function $llvm_AlwaysInline_llvm$_memcpy(dest, src, len) { + let dest_addr := dest + let src_addr := src + let dest_end := add(dest, and(len, sub(0, 32))) + for { } lt(dest_addr, dest_end) {} { + mstore(dest_addr, mload(src_addr)) + dest_addr := add(dest_addr, 32) + src_addr := add(src_addr, 32) + } + + let rest_len := and(len, 31) + if rest_len { + $llvm_AlwaysInline_llvm$_copyRest(dest_addr, mload(src_addr), rest_len) + } } - - addr := mload(0) - - let gasLeft - switch result - case 0 { - gasLeft := _saveReturndataAfterEVMCall(0, 0) + + function $llvm_AlwaysInline_llvm$_memsetToZero(dest,len) { + let dest_end := add(dest, and(len, sub(0, 32))) + for {let i := dest} lt(i, dest_end) { i := add(i, 32) } { + mstore(i, 0) } - default { - gasLeft := _fetchConstructorReturnGas() + + let rest_len := and(len, 31) + if rest_len { + $llvm_AlwaysInline_llvm$_copyRest(dest_end, 0, rest_len) } - - let gasUsed := sub(gasForTheCall, gasLeft) - evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - - _popEVMFrame() - - let back - - popStackCheck(sp, evmGasLeft, 4) - back, sp := popStackItemWithoutCheck(sp) - mstore(sub(offset, 0x20), back) - back, sp := popStackItemWithoutCheck(sp) - mstore(sub(offset, 0x40), back) - back, sp := popStackItemWithoutCheck(sp) - mstore(sub(offset, 0x60), back) - back, sp := popStackItemWithoutCheck(sp) - mstore(sub(offset, 0x80), back) - } + } function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { evmGasLeft := chargeGas(evmGas, 100) @@ -4673,21 +4432,12 @@ object "EVMInterpreter" { } evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - let len_32 := shr(5, len) - for {let i := 0} lt(i, len_32) { i := add(i, 1) } { - mstore(add(dest,shl(5,i)),0) - } - let size_32 := shl(5,len_32) - let rest_32 := sub(len, size_32) - for {let i := 0} lt(i, rest_32) { i := add(i, 1) } { - mstore8(add(dest,add(size_32,i)),0) - } + $llvm_AlwaysInline_llvm$_memsetToZero(dest, len) // Gets the code from the addr - if iszero(iszero(_getRawCodeHash(addr))) { + if and(iszero(iszero(_getRawCodeHash(addr))),gt(len,0)) { pop(_fetchDeployedCodeWithDest(addr, offset, len,add(dest,MEM_OFFSET_INNER()))) } - } function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { @@ -4704,9 +4454,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) - - checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { revertWithGas(evmGasLeft) @@ -4727,7 +4476,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) let result, addr - result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,false,0) + result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0) switch result case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } @@ -4749,9 +4498,8 @@ object "EVMInterpreter" { size, sp := popStackItemWithoutCheck(sp) salt, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) - - checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { revertWithGas(evmGasLeft) @@ -4771,19 +4519,6 @@ object "EVMInterpreter" { shr(2, add(size, 31)) )) - { - let hashedBytecode := keccak256(add(MEM_OFFSET_INNER(), offset), size) - mstore8(0, 0xFF) - mstore(0x01, shl(0x60, address())) - mstore(0x15, salt) - mstore(0x35, hashedBytecode) - } - - addr := and( - keccak256(0, 0x55), - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - ) - result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt) } @@ -4818,7 +4553,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -4830,7 +4565,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -4842,7 +4577,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -4854,7 +4589,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -4866,7 +4601,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -4878,7 +4613,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -4890,7 +4625,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -4902,7 +4637,7 @@ object "EVMInterpreter" { let a, b, N - popPushStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, evmGasLeft, 3) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) N, sp := popStackItemWithoutCheck(sp) @@ -4928,7 +4663,7 @@ object "EVMInterpreter" { let a, exponent - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) exponent, sp := popStackItemWithoutCheck(sp) @@ -4947,7 +4682,7 @@ object "EVMInterpreter" { let b, x - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) b, sp := popStackItemWithoutCheck(sp) x, sp := popStackItemWithoutCheck(sp) @@ -4959,7 +4694,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -4971,7 +4706,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -4983,7 +4718,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -4995,7 +4730,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -5007,7 +4742,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -5019,7 +4754,7 @@ object "EVMInterpreter" { let a - popPushStackCheck(sp, evmGasLeft, 1) + popStackCheck(sp, evmGasLeft, 1) a, sp := popStackItemWithoutCheck(sp) sp := pushStackItemWithoutCheck(sp, iszero(a)) @@ -5030,7 +4765,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -5042,7 +4777,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -5054,7 +4789,7 @@ object "EVMInterpreter" { let a, b - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) a, sp := popStackItemWithoutCheck(sp) b, sp := popStackItemWithoutCheck(sp) @@ -5066,7 +4801,7 @@ object "EVMInterpreter" { let a - popPushStackCheck(sp, evmGasLeft, 1) + popStackCheck(sp, evmGasLeft, 1) a, sp := popStackItemWithoutCheck(sp) sp := pushStackItemWithoutCheck(sp, not(a)) @@ -5077,7 +4812,7 @@ object "EVMInterpreter" { let i, x - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) i, sp := popStackItemWithoutCheck(sp) x, sp := popStackItemWithoutCheck(sp) @@ -5089,7 +4824,7 @@ object "EVMInterpreter" { let shift, value - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) shift, sp := popStackItemWithoutCheck(sp) value, sp := popStackItemWithoutCheck(sp) @@ -5101,7 +4836,7 @@ object "EVMInterpreter" { let shift, value - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) shift, sp := popStackItemWithoutCheck(sp) value, sp := popStackItemWithoutCheck(sp) @@ -5113,7 +4848,7 @@ object "EVMInterpreter" { let shift, value - popPushStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 2) shift, sp := popStackItemWithoutCheck(sp) value, sp := popStackItemWithoutCheck(sp) @@ -5129,8 +4864,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size, MEM_OFFSET_INNER(), evmGasLeft) - checkMemOverflow(add(MEM_OFFSET_INNER(), add(offset, size)), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) let keccak := keccak256(add(MEM_OFFSET_INNER(), offset), size) // When an offset is first accessed (either read or write), memory may trigger @@ -5161,7 +4896,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItem(sp, balance(addr), evmGasLeft) + sp := pushStackItemWithoutCheck(sp, balance(addr)) ip := add(ip, 1) } case 0x32 { // OP_ORIGIN @@ -5187,7 +4922,7 @@ object "EVMInterpreter" { let i - popPushStackCheck(sp, evmGasLeft, 1) + popStackCheck(sp, evmGasLeft, 1) i, sp := popStackItemWithoutCheck(sp) sp := pushStackItemWithoutCheck(sp, calldataload(i)) @@ -5212,13 +4947,9 @@ object "EVMInterpreter" { checkMultipleOverflow(offset,size,MEM_OFFSET_INNER(), evmGasLeft) checkMultipleOverflow(destOffset,size,MEM_OFFSET_INNER(), evmGasLeft) + // TODO invalid? if or(gt(add(add(offset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM()), gt(add(add(destOffset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM())) { - for { let i := 0 } lt(i, size) { i := add(i, 1) } { - mstore8( - add(add(destOffset, MEM_OFFSET_INNER()), i), - 0 - ) - } + $llvm_AlwaysInline_llvm$_memsetToZero(add(destOffset, MEM_OFFSET_INNER()), size) } // dynamicGas = 3 * minimum_word_size + memory_expansion_cost @@ -5263,12 +4994,7 @@ object "EVMInterpreter" { revertWithGas(evmGasLeft) } - for { let i := 0 } lt(i, len) { i := add(i, 1) } { - mstore8( - add(dst, i), - shr(248, mload(add(offset, i))) - ) - } + $llvm_AlwaysInline_llvm$_memcpy(dst, offset, len) ip := add(ip, 1) } case 0x3A { // OP_GASPRICE @@ -5288,14 +5014,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - // TODO: check, the .sol uses extcodesize directly, but it doesn't seem to work - // if a contract is created it works, but if the address is a zkSync's contract - // what happens? - // sp := pushStackItem(sp, extcodesize(addr), evmGasLeft) - - switch _isEVM(addr) - case 0 { sp := pushStackItem(sp, extcodesize(addr), evmGasLeft) } - default { sp := pushStackItem(sp, _fetchDeployedCodeLen(addr), evmGasLeft) } + sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY @@ -5318,9 +5037,6 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) len, sp := popStackItemWithoutCheck(sp) - // TODO: check if these conditions are met - // The addition offset + size overflows. - // offset + size is larger than RETURNDATASIZE. checkOverflow(offset,len, evmGasLeft) if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { revertWithGas(evmGasLeft) @@ -5328,7 +5044,7 @@ object "EVMInterpreter" { // minimum_word_size = (size + 31) / 32 // dynamicGas = 3 * minimum_word_size + memory_expansion_cost - checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(offset, evmGasLeft) let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dest, len))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -5348,16 +5064,16 @@ object "EVMInterpreter" { ip := add(ip, 1) if iszero(addr) { - sp := pushStackItem(sp, 0, evmGasLeft) + sp := pushStackItemWithoutCheck(sp, 0) continue } - sp := pushStackItem(sp, extcodehash(addr), evmGasLeft) + sp := pushStackItemWithoutCheck(sp, extcodehash(addr)) } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) let blockNumber - popPushStackCheck(sp, evmGasLeft, 1) + popStackCheck(sp, evmGasLeft, 1) blockNumber, sp := popStackItemWithoutCheck(sp) sp := pushStackItemWithoutCheck(sp, blockhash(blockNumber)) @@ -5418,13 +5134,12 @@ object "EVMInterpreter" { offset, sp := popStackItem(sp, evmGasLeft) - checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) let memValue := mload(add(MEM_OFFSET_INNER(), offset)) - sp := pushStackItem(sp, memValue, evmGasLeft) + sp := pushStackItemWithoutCheck(sp, memValue) ip := add(ip, 1) } case 0x52 { // OP_MSTORE @@ -5436,11 +5151,10 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) value, sp := popStackItemWithoutCheck(sp) - checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) mstore(add(MEM_OFFSET_INNER(), offset), value) ip := add(ip, 1) } @@ -5453,11 +5167,10 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) value, sp := popStackItemWithoutCheck(sp) - checkMemOverflow(add(offset, MEM_OFFSET_INNER()), evmGasLeft) + checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 1)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) mstore8(add(MEM_OFFSET_INNER(), offset), value) ip := add(ip, 1) } @@ -5481,7 +5194,7 @@ object "EVMInterpreter" { let _wasW, _orgV := warmSlot(key, value) } - sp := pushStackItem(sp,value, evmGasLeft) + sp := pushStackItemWithoutCheck(sp,value) ip := add(ip, 1) } case 0x55 { // OP_SSTORE @@ -5541,6 +5254,10 @@ object "EVMInterpreter" { if iszero(eq(nextOpcode, 0x5B)) { revertWithGas(evmGasLeft) } + + // execute JUMPDEST immediately + evmGasLeft := chargeGas(evmGasLeft, 1) + ip := add(ip, 1) } case 0x57 { // OP_JUMPI evmGasLeft := chargeGas(evmGasLeft, 10) @@ -5563,6 +5280,10 @@ object "EVMInterpreter" { if iszero(eq(nextOpcode, 0x5B)) { revertWithGas(evmGasLeft) } + + // execute JUMPDEST immediately + evmGasLeft := chargeGas(evmGasLeft, 1) + ip := add(ip, 1) } case 0x58 { // OP_PC evmGasLeft := chargeGas(evmGasLeft, 2) @@ -5595,7 +5316,7 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 100) let key - popPushStackCheck(sp, evmGasLeft, 1) + popStackCheck(sp, evmGasLeft, 1) key, sp := popStackItemWithoutCheck(sp) sp := pushStackItemWithoutCheck(sp, tload(key)) @@ -5623,26 +5344,14 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) + // TODO overflow checks + checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemOverflowByOffset(add(destOffset, size), evmGasLeft) + expandMemory(add(destOffset, size)) expandMemory(add(offset, size)) - let oldSize := mul(mload(MEM_OFFSET()),32) - if gt(add(oldSize,size),MAX_POSSIBLE_MEM()) { - revertWithGas(evmGasLeft) - } - - for { let i := 0 } lt(i, size) { i := add(i, 1) } { - mstore8( - add(add(oldSize,MEM_OFFSET_INNER()), i), - shr(248,mload(add(add(offset,MEM_OFFSET_INNER()), i))) - ) - } - for { let i := 0 } lt(i, size) { i := add(i, 1) } { - mstore8( - add(add(destOffset,MEM_OFFSET_INNER()), i), - shr(248,mload(add(add(oldSize,MEM_OFFSET_INNER()), i))) - ) - } + mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) ip := add(ip, 1) } case 0x5F { // OP_PUSH0 @@ -6081,8 +5790,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) - checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -6104,8 +5813,8 @@ object "EVMInterpreter" { size, sp := popStackItemWithoutCheck(sp) topic1, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) - checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -6126,8 +5835,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) - checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -6155,9 +5864,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) - - checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -6186,8 +5894,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset, size,MEM_OFFSET_INNER(), evmGasLeft) - checkMemOverflow(add(add(offset, MEM_OFFSET_INNER()), size), evmGasLeft) + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -6268,6 +5976,7 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) + // TODO invalid? ensureAcceptableMemLocation(offset) ensureAcceptableMemLocation(size) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) diff --git a/system-contracts/contracts/EvmInterpreterFunctions.template.yul b/system-contracts/contracts/EvmInterpreterFunctions.template.yul new file mode 100644 index 000000000..f53c079d8 --- /dev/null +++ b/system-contracts/contracts/EvmInterpreterFunctions.template.yul @@ -0,0 +1,1467 @@ +function SYSTEM_CONTRACTS_OFFSET() -> offset { + offset := 0x8000 +} + +function ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008002 +} + +function NONCE_HOLDER_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008003 +} + +function DEPLOYER_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008006 +} + +function CODE_ADDRESS_CALL_ADDRESS() -> addr { + addr := 0x000000000000000000000000000000000000FFFE +} + +function CODE_ORACLE_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008012 +} + +function EVM_GAS_MANAGER_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008013 +} + +function CALLFLAGS_CALL_ADDRESS() -> addr { + addr := 0x000000000000000000000000000000000000FFEF +} + +function DEBUG_SLOT_OFFSET() -> offset { + offset := mul(32, 32) +} + +function LAST_RETURNDATA_SIZE_OFFSET() -> offset { + offset := add(DEBUG_SLOT_OFFSET(), mul(5, 32)) +} + +function STACK_OFFSET() -> offset { + offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 32) +} + +function BYTECODE_OFFSET() -> offset { + offset := add(STACK_OFFSET(), mul(1024, 32)) +} + +function INF_PASS_GAS() -> inf { + inf := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +} + +function MAX_POSSIBLE_BYTECODE() -> max { + max := 32000 +} + +function MEM_OFFSET() -> offset { + offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_BYTECODE()) +} + +function MEM_OFFSET_INNER() -> offset { + offset := add(MEM_OFFSET(), 32) +} + +function MAX_POSSIBLE_MEM() -> max { + max := 0x100000 // 1MB +} + +function MAX_MEMORY_FRAME() -> max { + max := add(MEM_OFFSET_INNER(), MAX_POSSIBLE_MEM()) +} + +function MAX_UINT() -> max_uint { + max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +} + +// It is the responsibility of the caller to ensure that ip >= BYTECODE_OFFSET + 32 +function readIP(ip,maxAcceptablePos) -> opcode { + if gt(ip, maxAcceptablePos) { + revert(0, 0) + } + + opcode := and(mload(sub(ip, 31)), 0xff) +} + +function readBytes(start, maxAcceptablePos,length) -> value { + if gt(add(start,sub(length,1)), maxAcceptablePos) { + revert(0, 0) + } + value := shr(mul(8,sub(32,length)),mload(start)) +} + +function dupStackItem(sp, evmGas, position) -> newSp, evmGasLeft { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, sub(position, 1))) + + if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + let dup := mload(tempSp) + + newSp := add(sp, 0x20) + mstore(newSp, dup) +} + +function swapStackItem(sp, evmGas, position) -> evmGasLeft { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, position)) + + if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + + let s2 := mload(sp) + let s1 := mload(tempSp) + + mstore(sp, s1) + mstore(tempSp, s2) +} + +function popStackItem(sp, evmGasLeft) -> a, newSp { + // We can not return any error here, because it would break compatibility + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + a := mload(sp) + newSp := sub(sp, 0x20) +} + +function pushStackItem(sp, item, evmGasLeft) -> newSp { + if or(gt(sp, BYTECODE_OFFSET()), eq(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + newSp := add(sp, 0x20) + mstore(newSp, item) +} + +function popStackItemWithoutCheck(sp) -> a, newSp { + a := mload(sp) + newSp := sub(sp, 0x20) +} + +function pushStackItemWithoutCheck(sp, item) -> newSp { + newSp := add(sp, 0x20) + mstore(newSp, item) +} + +function popStackCheck(sp, evmGasLeft, numInputs) { + if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } +} + +function pushStackCheck(sp, evmGasLeft, numInputs) { + if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } +} + +function getCodeAddress() -> addr { + addr := verbatim_0i_1o("code_source") +} + +function loadReturndataIntoActivePtr() { + verbatim_0i_0o("return_data_ptr_to_active") +} + +function loadCalldataIntoActivePtr() { + verbatim_0i_0o("calldata_ptr_to_active") +} + +function getActivePtrDataSize() -> size { + size := verbatim_0i_1o("active_ptr_data_size") +} + +function copyActivePtrData(_dest, _source, _size) { + verbatim_3i_0o("active_ptr_data_copy", _dest, _source, _size) +} + +function ptrAddIntoActive(_dest) { + verbatim_1i_0o("active_ptr_add_assign", _dest) +} + +function ptrShrinkIntoActive(_dest) { + verbatim_1i_0o("active_ptr_shrink_assign", _dest) +} + +function _getRawCodeHash(account) -> hash { + mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) + mstore(4, account) + + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + hash := mload(0) +} + +function _getCodeHash(account) -> hash { + // function getCodeHash(uint256 _input) external view override returns (bytes32) + mstore(0, 0xE03FE17700000000000000000000000000000000000000000000000000000000) + mstore(4, account) + + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + hash := mload(0) +} + +function getIsStaticFromCallFlags() -> isStatic { + isStatic := verbatim_0i_1o("get_global::call_flags") + isStatic := iszero(iszero(and(isStatic, 0x04))) +} + +// Basically performs an extcodecopy, while returning the length of the bytecode. +function _fetchDeployedCode(addr, _offset, _len) -> codeLen { + codeLen := _fetchDeployedCodeWithDest(addr, 0, _len, _offset) +} + +// Basically performs an extcodecopy, while returning the length of the bytecode. +function _fetchDeployedCodeWithDest(addr, _offset, _len, dest) -> codeLen { + let codeHash := _getRawCodeHash(addr) + + mstore(0, codeHash) + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + // The first word is the true length of the bytecode + returndatacopy(0, 0, 32) + codeLen := mload(0) + + if gt(_len, codeLen) { + _len := codeLen + } + + returndatacopy(dest, add(32,_offset), _len) +} + +// Returns the length of the bytecode. +function _fetchDeployedCodeLen(addr) -> codeLen { + let codeHash := _getRawCodeHash(addr) + + switch shr(248, codeHash) + case 1 { + // EraVM + let codeLengthInWords := and(shr(224, codeHash), 0xffff) + codeLen := shl(5, codeLengthInWords) // codeLengthInWords * 32 + } + case 2 { + // EVM + let codeLengthInBytes := and(shr(224, codeHash), 0xffff) + codeLen := codeLengthInBytes + } +} + +function getDeployedBytecode() { + let codeLen := _fetchDeployedCode( + getCodeAddress(), + add(BYTECODE_OFFSET(), 32), + MAX_POSSIBLE_BYTECODE() + ) + + mstore(BYTECODE_OFFSET(), codeLen) +} + +function consumeEvmFrame() -> passGas, isStatic, callerEVM { + // function consumeEvmFrame() external returns (uint256 passGas, bool isStatic) + mstore(0, 0x04C14E9E00000000000000000000000000000000000000000000000000000000) + + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 4, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) + + if iszero(success) { + // Should never happen + revert(0, 0) + } + + returndatacopy(0,0,64) + + passGas := mload(0) + isStatic := mload(32) + + if iszero(eq(passGas, INF_PASS_GAS())) { + callerEVM := true + } +} + +function chargeGas(prevGas, toCharge) -> gasRemaining { + if lt(prevGas, toCharge) { + revertWithGas(0) + } + + gasRemaining := sub(prevGas, toCharge) +} + +function getMax(a, b) -> max { + max := b + if gt(a, b) { + max := a + } +} + +function getMin(a, b) -> min { + min := b + if lt(a, b) { + min := a + } +} + +function bitLength(n) -> bitLen { + for { } gt(n, 0) { } { // while(n > 0) + if iszero(n) { + bitLen := 1 + break + } + n := shr(1, n) + bitLen := add(bitLen, 1) + } +} + +function bitMaskFromBytes(nBytes) -> bitMask { + bitMask := sub(exp(2, mul(nBytes, 8)), 1) // 2**(nBytes*8) - 1 +} +// The gas cost mentioned here is purely the cost of the contract, +// and does not consider the cost of the call itself nor the instructions +// to put the parameters in memory. +// Take into account MEM_OFFSET_INNER() when passing the argsOffset +function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { + switch addr + case 0x01 { // ecRecover + gasToCharge := 3000 + } + case 0x02 { // SHA2-256 + gasToCharge := 60 + let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 + gasToCharge := add(gasToCharge, mul(12, dataWordSize)) + } + case 0x03 { // RIPEMD-160 + gasToCharge := 600 + let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 + gasToCharge := add(gasToCharge, mul(120, dataWordSize)) + } + case 0x04 { // identity + gasToCharge := 15 + let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 + gasToCharge := add(gasToCharge, mul(3, dataWordSize)) + } + // [0; 31] (32 bytes) Bsize Byte size of B + // [32; 63] (32 bytes) Esize Byte size of E + // [64; 95] (32 bytes) Msize Byte size of M + /* + def calculate_iteration_count(exponent_length, exponent): + iteration_count = 0 + if exponent_length <= 32 and exponent == 0: iteration_count = 0 + elif exponent_length <= 32: iteration_count = exponent.bit_length() - 1 + elif exponent_length > 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1) + return max(iteration_count, 1) + def calculate_gas_cost(base_length, modulus_length, exponent_length, exponent): + multiplication_complexity = calculate_multiplication_complexity(base_length, modulus_length) + iteration_count = calculate_iteration_count(exponent_length, exponent) + return max(200, math.floor(multiplication_complexity * iteration_count / 3)) + */ + // modexp gas cost EIP below + // https://eips.ethereum.org/EIPS/eip-2565 + case 0x05 { // modexp + let mulComplex + let Bsize := mload(argsOffset) + let Esize := mload(add(argsOffset, 0x20)) + + { + let words := getMax(Bsize, mload(add(argsOffset, 0x40))) // shr(3, x) == x/8 + if and(lt(words, 64), eq(words, 64)){ + // if x <= 64: return x ** 2 + mulComplex := mul(words, words) + } + if and(and(lt(words, 1024), eq(words, 1024)), gt(words, 64)){ + // elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072 + mulComplex := sub(add(shr(2, mul(words, words)), mul(96, words)), 3072) + } + if gt(words, 64) { + // else: return x ** 2 // 16 + 480 * x - 199680 + mulComplex := sub(add(shr(4, mul(words, words)), mul(480, words)), 199680) + } + } + + // [96 + Bsize; 96 + Bsize + Esize] E + let exponentFirst256, exponentIsZero, exponentBitLen + if or(lt(Esize, 32), eq(Esize, 32)) { + // Maybe there isn't exactly 32 bytes, so a mask should be applied + exponentFirst256 := mload(add(add(argsOffset, 0x60), Bsize)) + exponentBitLen := bitLength(exponentFirst256) + exponentIsZero := iszero(and(exponentFirst256, bitMaskFromBytes(Esize))) + } + if gt(Esize, 32) { + exponentFirst256 := mload(add(add(argsOffset, 0x60), Bsize)) + exponentIsZero := iszero(exponentFirst256) + let exponentNext + // This is done because the first 32bytes of the exponent were loaded + for { let i := 0 } lt(i, div(Esize, 32)) { i := add(i, 1) Esize := sub(Esize, 32) } { // check every 32bytes + // Maybe there isn't exactly 32 bytes, so a mask should be applied + exponentNext := mload(add(add(add(argsOffset, 0x60), Bsize), add(mul(i, 32), 32))) + exponentBitLen := add(bitLength(exponentNext), mul(mul(32, 8), add(i, 1))) + if iszero(iszero(and(exponentNext, bitMaskFromBytes(Esize)))) { + exponentIsZero := false + } + } + } + + // if exponent_length <= 32 and exponent == 0: iteration_count = 0 + // return max(iteration_count, 1) + let iterationCount := 1 + // elif exponent_length <= 32: iteration_count = exponent.bit_length() - 1 + if and(lt(Esize, 32), iszero(exponentIsZero)) { + iterationCount := sub(exponentBitLen, 1) + } + // elif exponent_length > 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1) + if gt(Esize, 32) { + iterationCount := add(mul(8, sub(Esize, 32)), sub(bitLength(and(exponentFirst256, MAX_UINT())), 1)) + } + + gasToCharge := getMax(200, div(mul(mulComplex, iterationCount), 3)) + } + // ecAdd ecMul ecPairing EIP below + // https://eips.ethereum.org/EIPS/eip-1108 + case 0x06 { // ecAdd + // The gas cost is fixed at 150. However, if the input + // does not allow to compute a valid result, all the gas sent is consumed. + gasToCharge := 150 + } + case 0x07 { // ecMul + // The gas cost is fixed at 6000. However, if the input + // does not allow to compute a valid result, all the gas sent is consumed. + gasToCharge := 6000 + } + // 35,000 * k + 45,000 gas, where k is the number of pairings being computed. + // The input must always be a multiple of 6 32-byte values. + case 0x08 { // ecPairing + gasToCharge := 45000 + let k := div(argsSize, 0xC0) // 0xC0 == 6*32 + gasToCharge := add(gasToCharge, mul(k, 35000)) + } + case 0x09 { // blake2f + // argsOffset[0; 3] (4 bytes) Number of rounds (big-endian uint) + gasToCharge := and(mload(argsOffset), 0xFFFFFFFF) // last 4bytes + } + default { + gasToCharge := 0 + } +} + +function checkMemOverflowByOffset(offset, evmGasLeft) { + if gt(offset, MAX_POSSIBLE_MEM()) { + mstore(0, evmGasLeft) + revert(0, 32) + } +} + +function checkMemOverflow(location, evmGasLeft) { + if gt(location, MAX_MEMORY_FRAME()) { + mstore(0, evmGasLeft) + revert(0, 32) + } +} + +function checkMultipleOverflow(data1, data2, data3, evmGasLeft) { + checkOverflow(data1, data2, evmGasLeft) + checkOverflow(data1, data3, evmGasLeft) + checkOverflow(data2, data3, evmGasLeft) + checkOverflow(add(data1, data2), data3, evmGasLeft) +} + +function checkOverflow(data1, data2, evmGasLeft) { + if lt(add(data1, data2), data2) { + revertWithGas(evmGasLeft) + } +} + +function revertWithGas(evmGasLeft) { + mstore(0, evmGasLeft) + revert(0, 32) +} + +// This function can overflow, it is the job of the caller to ensure that it does not. +// The argument to this function is the offset into the memory region IN BYTES. +function expandMemory(newSize) -> gasCost { + let oldSizeInWords := mload(MEM_OFFSET()) + + // The add 31 here before dividing is there to account for misaligned + // memory expansions, where someone calls this with a newSize that is not + // a multiple of 32. For instance, if someone calls it with an offset of 33, + // the new size in words should be 2, not 1, but dividing by 32 will give 1. + // Adding 31 solves it. + let newSizeInWords := div(add(newSize, 31), 32) + + if gt(newSizeInWords, oldSizeInWords) { + let new_minus_old := sub(newSizeInWords, oldSizeInWords) + gasCost := add(mul(3,new_minus_old), div(mul(new_minus_old,add(newSizeInWords,oldSizeInWords)),512)) + + mstore(MEM_OFFSET(), newSizeInWords) + } +} + +// Essentially a NOP that will not get optimized away by the compiler +function $llvm_NoInline_llvm$_unoptimized() { + pop(1) +} + +function printHex(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebde) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() +} + +function printString(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdf) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() +} + +function isSlotWarm(key) -> isWarm { + mstore(0, 0x482D2E7400000000000000000000000000000000000000000000000000000000) + mstore(4, key) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + isWarm := mload(0) +} + +function warmSlot(key,currentValue) -> isWarm, originalValue { + mstore(0, 0xBDF7816000000000000000000000000000000000000000000000000000000000) + mstore(4, key) + mstore(36,currentValue) + + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 68, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + returndatacopy(0, 0, 64) + + isWarm := mload(0) + originalValue := mload(32) +} + +function MAX_SYSTEM_CONTRACT_ADDR() -> ret { + ret := 0x000000000000000000000000000000000000ffff +} + +/// @dev Checks whether an address is an EOA (i.e. has not code deployed on it) +/// @param addr The address to check +function isEOA(addr) -> ret { + ret := 0 + if gt(addr, MAX_SYSTEM_CONTRACT_ADDR()) { + ret := iszero(_getRawCodeHash(addr)) + } +} + +function incrementNonce(addr) { + mstore(0, 0x306395C600000000000000000000000000000000000000000000000000000000) + mstore(4, addr) + + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 36, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := NONCE_HOLDER_SYSTEM_CONTRACT() + let result := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) + + if iszero(result) { + revert(0, 0) + } +} + +function getFarCallABI( + dataOffset, + memoryPage, + dataStart, + dataLength, + gasPassed, + shardId, + forwardingMode, + isConstructorCall, + isSystemCall +) -> ret { + let farCallAbi := 0 + farCallAbi := or(farCallAbi, dataOffset) + farCallAbi := or(farCallAbi, shl(64, dataStart)) + farCallAbi := or(farCallAbi, shl(96, dataLength)) + farCallAbi := or(farCallAbi, shl(192, gasPassed)) + farCallAbi := or(farCallAbi, shl(224, shardId)) + farCallAbi := or(farCallAbi, shl(232, forwardingMode)) + farCallAbi := or(farCallAbi, shl(248, 1)) + ret := farCallAbi +} + +function ensureAcceptableMemLocation(location) { + if gt(location,MAX_POSSIBLE_MEM()) { + revert(0,0) // Check if this is what's needed + } +} + +function addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) -> newOffset,newSize { + newOffset := offset + newSize := size + if eq(isCallerEVM,1) { + // include gas + let previousValue := mload(sub(offset,32)) + mstore(sub(offset,32),evmGasLeft) + //mstore(sub(offset,32),previousValue) // Im not sure why this is needed, it was like this in the solidity code, + // but it appears to rewrite were we want to store the gas + + newOffset := sub(offset, 32) + newSize := add(size, 32) + } +} + +function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { + mstore(0, 0x8DB2BA7800000000000000000000000000000000000000000000000000000000) + mstore(4, addr) + + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 36, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + returndatacopy(0, 0, 32) + isWarm := mload(0) +} + +function getRawNonce(addr) -> nonce { + mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) + mstore(4, addr) + + let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(result) { + revert(0, 0) + } + + nonce := mload(0) +} + +function _isEVM(_addr) -> isEVM { + // bytes4 selector = ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM.selector; (0x8c040477) + // function isAccountEVM(address _addr) external view returns (bool); + // IAccountCodeStorage constant ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT = IAccountCodeStorage( + // address(SYSTEM_CONTRACTS_OFFSET + 0x02) + // ); + + mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) + mstore(4, _addr) + + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + isEVM := mload(0) +} + +function _pushEVMFrame(_passGas, _isStatic) { + // function pushEVMFrame(uint256 _passGas, bool _isStatic) external + + mstore(0, 0xEAD7715600000000000000000000000000000000000000000000000000000000) + mstore(4, _passGas) + mstore(36, _isStatic) + + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 68, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + + let to := EVM_GAS_MANAGER_CONTRACT() + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } +} + +function _popEVMFrame() { + // function popEVMFrame() external + + let farCallAbi := getFarCallABI( + 0, + 0, + 0, + 4, + gas(), + // Only rollup is supported for now + 0, + 0, + 0, + 1 + ) + + let to := EVM_GAS_MANAGER_CONTRACT() + + mstore(0, 0xE467D2F000000000000000000000000000000000000000000000000000000000) + + let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) + if iszero(success) { + // This error should never happen + revert(0, 0) + } +} + +// Each evm gas is 5 zkEVM one +function GAS_DIVISOR() -> gas_div { gas_div := 5 } +function EVM_GAS_STIPEND() -> gas_stipend { gas_stipend := shl(30, 1) } // 1 << 30 +function OVERHEAD() -> overhead { overhead := 2000 } + +// From precompiles/CodeOracle +function DECOMMIT_COST_PER_WORD() -> cost { cost := 4 } +function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 + +function _calcEVMGas(_zkevmGas) -> calczkevmGas { + calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) +} + +function getEVMGas() -> evmGas { + let _gas := gas() + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) + + switch lt(_gas, requiredGas) + case 1 { + evmGas := 0 + } + default { + evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) + } +} + +function _getZkEVMGas(_evmGas, addr) -> zkevmGas { + zkevmGas := mul(_evmGas, GAS_DIVISOR()) + let byteSize := extcodesize(addr) + let should_ceil := mod(byteSize, 32) + if gt(should_ceil, 0) { + byteSize := add(byteSize, sub(32, should_ceil)) + } + let decommitGasCost := mul(div(byteSize,32), DECOMMIT_COST_PER_WORD()) + zkevmGas := sub(zkevmGas, decommitGasCost) + if gt(zkevmGas, UINT32_MAX()) { + zkevmGas := UINT32_MAX() + } +} + +function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft{ + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + let rtsz := returndatasize() + + loadReturndataIntoActivePtr() + + // if (rtsz > 31) + switch gt(rtsz, 31) + case 0 { + // Unexpected return data. + _gasLeft := 0 + _eraseReturndataPointer() + } + default { + returndatacopy(0, 0, 32) + _gasLeft := mload(0) + + // We copy as much returndata as possible without going over the + // returndata size. + switch lt(sub(rtsz, 32), _outputLen) + case 0 { returndatacopy(_outputOffset, 32, _outputLen) } + default { returndatacopy(_outputOffset, 32, sub(rtsz, 32)) } + + mstore(lastRtSzOffset, sub(rtsz, 32)) + + // Skip the returnData + ptrAddIntoActive(32) + } +} + +function _eraseReturndataPointer() { + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + + let activePtrSize := getActivePtrDataSize() + ptrShrinkIntoActive(and(activePtrSize, 0xFFFFFFFF))// uint32(activePtrSize) + mstore(lastRtSzOffset, 0) +} + +function _saveReturndataAfterZkEVMCall() { + loadReturndataIntoActivePtr() + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + + mstore(lastRtSzOffset, returndatasize()) +} + +function performStaticCall(oldSp,evmGasLeft) -> extraCost, sp { + let gasToPass,addr, argsOffset, argsSize, retOffset, retSize + + popStackCheck(oldSp, evmGasLeft, 6) + gasToPass, sp := popStackItemWithoutCheck(oldSp) + addr, sp := popStackItemWithoutCheck(sp) + argsOffset, sp := popStackItemWithoutCheck(sp) + argsSize, sp := popStackItemWithoutCheck(sp) + retOffset, sp := popStackItemWithoutCheck(sp) + retSize, sp := popStackItemWithoutCheck(sp) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + checkOverflow(argsOffset,argsSize, evmGasLeft) + checkOverflow(retOffset, retSize, evmGasLeft) + + checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) + + extraCost := 0 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + extraCost := 2500 + } + + { + let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) + extraCost := add(extraCost,maxExpand) + } + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + if gt(gasToPass, maxGasToPass) { + gasToPass := maxGasToPass + } + + let frameGasLeft + let success + switch _isEVM(addr) + case 0 { + // zkEVM native + gasToPass := _getZkEVMGas(gasToPass, addr) + let zkevmGasBefore := gas() + success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, add(MEM_OFFSET_INNER(), retOffset), retSize) + _saveReturndataAfterZkEVMCall() + + let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + + frameGasLeft := 0 + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) + } + } + default { + _pushEVMFrame(gasToPass, true) + success := staticcall(gasToPass, addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, 0, 0) + + frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + _popEVMFrame() + } + + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch iszero(precompileCost) + case 1 { + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + } + default { + extraCost := add(extraCost, precompileCost) + } + + sp := pushStackItem(sp, success, evmGasLeft) +} +function capGas(evmGasLeft,oldGasToPass) -> gasToPass { + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + gasToPass := oldGasToPass + if gt(oldGasToPass, maxGasToPass) { + gasToPass := maxGasToPass + } +} + +function getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) -> maxExpand{ + maxExpand := add(retOffset, retSize) + switch lt(maxExpand,add(argsOffset, argsSize)) + case 0 { + maxExpand := expandMemory(maxExpand) + } + default { + maxExpand := expandMemory(add(argsOffset, argsSize)) + } +} + +function _performCall(addr,gasToPass,value,argsOffset,argsSize,retOffset,retSize,isStatic) -> success, frameGasLeft, gasToPassNew{ + gasToPassNew := gasToPass + let is_evm := _isEVM(addr) + + switch isStatic + case 0 { + switch is_evm + case 0 { + // zkEVM native + gasToPassNew := _getZkEVMGas(gasToPassNew, addr) + let zkevmGasBefore := gas() + success := call(gasToPassNew, addr, value, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + + frameGasLeft := 0 + if gt(gasToPassNew, gasUsed) { + frameGasLeft := sub(gasToPassNew, gasUsed) + } + } + default { + _pushEVMFrame(gasToPassNew, isStatic) + success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + _popEVMFrame() + } + } + default { + if value { + revertWithGas(gasToPassNew) + } + success, frameGasLeft:= _performStaticCall( + is_evm, + gasToPassNew, + addr, + argsOffset, + argsSize, + retOffset, + retSize + ) + } +} + +function performCall(oldSp, evmGasLeft, isStatic) -> extraCost, sp { + let gasToPass,addr,value,argsOffset,argsSize,retOffset,retSize + + popStackCheck(oldSp, evmGasLeft, 7) + gasToPass, sp := popStackItemWithoutCheck(oldSp) + addr, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + argsOffset, sp := popStackItemWithoutCheck(sp) + argsSize, sp := popStackItemWithoutCheck(sp) + retOffset, sp := popStackItemWithoutCheck(sp) + retSize, sp := popStackItemWithoutCheck(sp) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + // static_gas = 0 + // dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + positive_value_cost + value_to_empty_account_cost + // code_execution_cost is the cost of the called code execution (limited by the gas parameter). + // If address is warm, then address_access_cost is 100, otherwise it is 2600. See section access sets. + // If value is not 0, then positive_value_cost is 9000. In this case there is also a call stipend that is given to make sure that a basic fallback function can be called. 2300 is thus removed from the cost, and also added to the gas input. + // If value is not 0 and the address given points to an empty account, then value_to_empty_account_cost is 25000. An account is empty if its balance is 0, its nonce is 0 and it has no code. + + extraCost := 0 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + extraCost := 2500 + } + + if gt(value, 0) { + extraCost := add(extraCost,6700) + gasToPass := add(gasToPass,2300) + } + + if and(isAddrEmpty(addr), gt(value, 0)) { + extraCost := add(extraCost,25000) + } + { + let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) + extraCost := add(extraCost,maxExpand) + } + gasToPass := capGas(evmGasLeft,gasToPass) + + argsOffset := add(argsOffset,MEM_OFFSET_INNER()) + retOffset := add(retOffset,MEM_OFFSET_INNER()) + + checkOverflow(argsOffset,argsSize, evmGasLeft) + checkOverflow(retOffset,retSize, evmGasLeft) + + checkMemOverflow(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflow(add(retOffset, retSize), evmGasLeft) + + let success, frameGasLeft + success, frameGasLeft, gasToPass:= _performCall( + addr, + gasToPass, + value, + argsOffset, + argsSize, + retOffset, + retSize, + isStatic + ) + + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch iszero(precompileCost) + case 1 { + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + } + default { + extraCost := add(extraCost, precompileCost) + } + sp := pushStackItem(sp,success, evmGasLeft) +} + +function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost { + let addr, gasToPass, argsOffset, argsSize, retOffset, retSize + + sp := oldSp + isStatic := oldIsStatic + + popStackCheck(sp, evmGasLeft, 6) + gasToPass, sp := popStackItemWithoutCheck(sp) + addr, sp := popStackItemWithoutCheck(sp) + argsOffset, sp := popStackItemWithoutCheck(sp) + argsSize, sp := popStackItemWithoutCheck(sp) + retOffset, sp := popStackItemWithoutCheck(sp) + retSize, sp := popStackItemWithoutCheck(sp) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + checkOverflow(argsOffset, argsSize, evmGasLeft) + checkOverflow(retOffset, retSize, evmGasLeft) + + checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) + + if iszero(_isEVM(addr)) { + revertWithGas(evmGasLeft) + } + + extraCost := 0 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + extraCost := 2500 + } + + { + let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) + extraCost := add(extraCost,maxExpand) + } + gasToPass := capGas(evmGasLeft,gasToPass) + + _pushEVMFrame(gasToPass, isStatic) + let success := delegatecall( + // We can not just pass all gas here to prevent overflow of zkEVM gas counter + EVM_GAS_STIPEND(), + addr, + add(MEM_OFFSET_INNER(), argsOffset), + argsSize, + 0, + 0 + ) + + let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + + _popEVMFrame() + + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch iszero(precompileCost) + case 1 { + extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + } + default { + extraCost := add(extraCost, precompileCost) + } + sp := pushStackItem(sp, success, evmGasLeft) +} + +function getMessageCallGas ( + _value, + _gas, + _gasLeft, + _memoryCost, + _extraGas +) -> gasPlusExtra, gasPlusStipend { + let callStipend := 2300 + if iszero(_value) { + callStipend := 0 + } + + switch lt(_gasLeft, add(_extraGas, _memoryCost)) + case 0 + { + let _gasTemp := sub(sub(_gasLeft, _extraGas), _memoryCost) + // From the Tangerine Whistle fork, gas is capped at all but one 64th (remaining_gas / 64) + // of the remaining gas of the current context. If a call tries to send more, the gas is + // changed to match the maximum allowed. + let maxGasToPass := sub(_gasTemp, shr(6, _gasTemp)) // _gas >> 6 == _gas/64 + if gt(_gas, maxGasToPass) { + _gas := maxGasToPass + } + gasPlusExtra := add(_gas, _extraGas) + gasPlusStipend := add(_gas, callStipend) + } + default { + gasPlusExtra := add(_gas, _extraGas) + gasPlusStipend := add(_gas, callStipend) + } +} + +function _performStaticCall( + _calleeIsEVM, + _calleeGas, + _callee, + _inputOffset, + _inputLen, + _outputOffset, + _outputLen +) -> success, _gasLeft { + switch _calleeIsEVM + case 0 { + // zkEVM native + _calleeGas := _getZkEVMGas(_calleeGas, _callee) + let zkevmGasBefore := gas() + success := staticcall(_calleeGas, _callee, _inputOffset, _inputLen, _outputOffset, _outputLen) + + _saveReturndataAfterZkEVMCall() + + let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + + _gasLeft := 0 + if gt(_calleeGas, gasUsed) { + _gasLeft := sub(_calleeGas, gasUsed) + } + } + default { + _pushEVMFrame(_calleeGas, true) + success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) + + _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) + _popEVMFrame() + } +} + +function isAddrEmpty(addr) -> isEmpty { + isEmpty := 0 + if iszero(extcodesize(addr)) { // YUL doesn't have short-circuit evaluation + if iszero(balance(addr)) { + if iszero(getRawNonce(addr)) { + isEmpty := 1 + } + } + } +} + +function _fetchConstructorReturnGas() -> gasLeft { + mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) + + let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + gasLeft := mload(0) +} + +function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt) -> result, evmGasLeft, addr { + pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) + + _eraseReturndataPointer() + + let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) + + if lt(selfbalance(),value) { + revertWithGas(evmGasLeftOld) + } + + offset := add(MEM_OFFSET_INNER(), offset) + + pushStackCheck(sp, evmGasLeftOld, 4) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80))) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60))) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40))) + sp := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20))) + + _pushEVMFrame(gasForTheCall, false) + + if isCreate2 { + // Create2EVM selector + mstore(sub(offset, 0x80), 0x4e96f4c0) + // salt + mstore(sub(offset, 0x60), salt) + // Where the arg starts (third word) + mstore(sub(offset, 0x40), 0x40) + // Length of the init code + mstore(sub(offset, 0x20), size) + + + result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) + } + + + if iszero(isCreate2) { + // CreateEVM selector + mstore(sub(offset, 0x60), 0xff311601) + // Where the arg starts (second word) + mstore(sub(offset, 0x40), 0x20) + // Length of the init code + mstore(sub(offset, 0x20), size) + + + result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) + } + + addr := mload(0) + + let gasLeft + switch result + case 0 { + gasLeft := _saveReturndataAfterEVMCall(0, 0) + } + default { + gasLeft := _fetchConstructorReturnGas() + } + + let gasUsed := sub(gasForTheCall, gasLeft) + evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) + + _popEVMFrame() + + let back + + // skipping check since we pushed exactly 4 items earlier + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x20), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x40), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x60), back) + back, sp := popStackItemWithoutCheck(sp) + mstore(sub(offset, 0x80), back) +} + +function $llvm_AlwaysInline_llvm$_copyRest(dest, val, len) { + let rest_bits := shl(3, len) + let upper_bits := sub(256, rest_bits) + let val_mask := shl(upper_bits, MAX_UINT()) + let val_masked := and(val, val_mask) + let dst_val := mload(dest) + let dst_mask := shr(rest_bits, MAX_UINT()) + let dst_masked := and(dst_val, dst_mask) + mstore(dest, or(val_masked, dst_masked)) +} + +function $llvm_AlwaysInline_llvm$_memcpy(dest, src, len) { + let dest_addr := dest + let src_addr := src + let dest_end := add(dest, and(len, sub(0, 32))) + for { } lt(dest_addr, dest_end) {} { + mstore(dest_addr, mload(src_addr)) + dest_addr := add(dest_addr, 32) + src_addr := add(src_addr, 32) + } + + let rest_len := and(len, 31) + if rest_len { + $llvm_AlwaysInline_llvm$_copyRest(dest_addr, mload(src_addr), rest_len) + } +} + +function $llvm_AlwaysInline_llvm$_memsetToZero(dest,len) { + let dest_end := add(dest, and(len, sub(0, 32))) + for {let i := dest} lt(i, dest_end) { i := add(i, 32) } { + mstore(i, 0) + } + + let rest_len := and(len, 31) + if rest_len { + $llvm_AlwaysInline_llvm$_copyRest(dest_end, 0, rest_len) + } +} + +function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { + evmGasLeft := chargeGas(evmGas, 100) + + let addr, dest, offset, len + popStackCheck(oldSp, evmGasLeft, 4) + addr, sp := popStackItemWithoutCheck(oldSp) + dest, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + len, sp := popStackItemWithoutCheck(sp) + + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost + // minimum_word_size = (size + 31) / 32 + + let dynamicGas := add( + mul(3, shr(5, add(len, 31))), + expandMemory(add(dest, len)) + ) + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + dynamicGas := add(dynamicGas, 2500) + } + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + $llvm_AlwaysInline_llvm$_memsetToZero(dest, len) + + // Gets the code from the addr + if and(iszero(iszero(_getRawCodeHash(addr))),gt(len,0)) { + pop(_fetchDeployedCodeWithDest(addr, offset, len,add(dest,MEM_OFFSET_INNER()))) + } +} + +function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { + evmGasLeft := chargeGas(evmGas, 32000) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let value, offset, size + + popStackCheck(oldSp, evmGasLeft, 3) + value, sp := popStackItemWithoutCheck(oldSp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) + + if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { + revertWithGas(evmGasLeft) + } + + if gt(value, balance(address())) { + revertWithGas(evmGasLeft) + } + + // dynamicGas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost + // minimum_word_size = (size + 31) / 32 + // init_code_cost = 2 * minimum_word_size + // code_deposit_cost = 200 * deployed_code_size + let dynamicGas := add( + shr(4, add(size, 31)), + expandMemory(add(offset, size)) + ) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + let result, addr + result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0) + + switch result + case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } + default { sp := pushStackItem(sp, addr, evmGasLeft) } +} + +function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr{ + evmGasLeft := chargeGas(evmGas, 32000) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let value, offset, size, salt + + popStackCheck(oldSp, evmGasLeft, 4) + value, sp := popStackItemWithoutCheck(oldSp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + salt, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) + + if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { + revertWithGas(evmGasLeft) + } + + if gt(value, balance(address())) { + revertWithGas(evmGasLeft) + } + + // dynamicGas = init_code_cost + hash_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost + // minimum_word_size = (size + 31) / 32 + // init_code_cost = 2 * minimum_word_size + // hash_cost = 6 * minimum_word_size + // code_deposit_cost = 200 * deployed_code_size + evmGasLeft := chargeGas(evmGasLeft, add( + expandMemory(add(offset, size)), + shr(2, add(size, 31)) + )) + + result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt) +} diff --git a/system-contracts/contracts/EvmInterpreterLoop.template.yul b/system-contracts/contracts/EvmInterpreterLoop.template.yul new file mode 100644 index 000000000..5880cd1f4 --- /dev/null +++ b/system-contracts/contracts/EvmInterpreterLoop.template.yul @@ -0,0 +1,1465 @@ +// stack pointer - index to first stack element; empty stack = -1 +let sp := sub(STACK_OFFSET(), 32) +// instruction pointer - index to next instruction. Not called pc because it's an +// actual yul/evm instruction. +let ip := add(BYTECODE_OFFSET(), 32) +let opcode + +let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) + +for { } true { } { + opcode := readIP(ip,maxAcceptablePos) + + switch opcode + case 0x00 { // OP_STOP + break + } + case 0x01 { // OP_ADD + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, add(a, b)) + ip := add(ip, 1) + } + case 0x02 { // OP_MUL + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, mul(a, b)) + ip := add(ip, 1) + } + case 0x03 { // OP_SUB + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sub(a, b)) + ip := add(ip, 1) + } + case 0x04 { // OP_DIV + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, div(a, b)) + ip := add(ip, 1) + } + case 0x05 { // OP_SDIV + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sdiv(a, b)) + ip := add(ip, 1) + } + case 0x06 { // OP_MOD + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, mod(a, b)) + ip := add(ip, 1) + } + case 0x07 { // OP_SMOD + evmGasLeft := chargeGas(evmGasLeft, 5) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, smod(a, b)) + ip := add(ip, 1) + } + case 0x08 { // OP_ADDMOD + evmGasLeft := chargeGas(evmGasLeft, 8) + + let a, b, N + + popStackCheck(sp, evmGasLeft, 3) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + N, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, addmod(a, b, N)) + ip := add(ip, 1) + } + case 0x09 { // OP_MULMOD + evmGasLeft := chargeGas(evmGasLeft, 8) + + let a, b, N + + popStackCheck(sp, evmGasLeft, 3) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + N, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItem(sp, mulmod(a, b, N), evmGasLeft) + ip := add(ip, 1) + } + case 0x0A { // OP_EXP + evmGasLeft := chargeGas(evmGasLeft, 10) + + let a, exponent + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + exponent, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, exp(a, exponent)) + + let to_charge := 0 + for {} gt(exponent,0) {} { // while exponent > 0 + to_charge := add(to_charge, 50) + exponent := shr(8, exponent) + } + evmGasLeft := chargeGas(evmGasLeft, to_charge) + ip := add(ip, 1) + } + case 0x0B { // OP_SIGNEXTEND + evmGasLeft := chargeGas(evmGasLeft, 5) + + let b, x + + popStackCheck(sp, evmGasLeft, 2) + b, sp := popStackItemWithoutCheck(sp) + x, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, signextend(b, x)) + ip := add(ip, 1) + } + case 0x10 { // OP_LT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, lt(a, b)) + ip := add(ip, 1) + } + case 0x11 { // OP_GT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, gt(a, b)) + ip := add(ip, 1) + } + case 0x12 { // OP_SLT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, slt(a, b)) + ip := add(ip, 1) + } + case 0x13 { // OP_SGT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sgt(a, b)) + ip := add(ip, 1) + } + case 0x14 { // OP_EQ + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, eq(a, b)) + ip := add(ip, 1) + } + case 0x15 { // OP_ISZERO + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a + + popStackCheck(sp, evmGasLeft, 1) + a, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, iszero(a)) + ip := add(ip, 1) + } + case 0x16 { // OP_AND + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, and(a,b)) + ip := add(ip, 1) + } + case 0x17 { // OP_OR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, or(a,b)) + ip := add(ip, 1) + } + case 0x18 { // OP_XOR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a, b + + popStackCheck(sp, evmGasLeft, 2) + a, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, xor(a, b)) + ip := add(ip, 1) + } + case 0x19 { // OP_NOT + evmGasLeft := chargeGas(evmGasLeft, 3) + + let a + + popStackCheck(sp, evmGasLeft, 1) + a, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, not(a)) + ip := add(ip, 1) + } + case 0x1A { // OP_BYTE + evmGasLeft := chargeGas(evmGasLeft, 3) + + let i, x + + popStackCheck(sp, evmGasLeft, 2) + i, sp := popStackItemWithoutCheck(sp) + x, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, byte(i, x)) + ip := add(ip, 1) + } + case 0x1B { // OP_SHL + evmGasLeft := chargeGas(evmGasLeft, 3) + + let shift, value + + popStackCheck(sp, evmGasLeft, 2) + shift, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, shl(shift, value)) + ip := add(ip, 1) + } + case 0x1C { // OP_SHR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let shift, value + + popStackCheck(sp, evmGasLeft, 2) + shift, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, shr(shift, value)) + ip := add(ip, 1) + } + case 0x1D { // OP_SAR + evmGasLeft := chargeGas(evmGasLeft, 3) + + let shift, value + + popStackCheck(sp, evmGasLeft, 2) + shift, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, sar(shift, value)) + ip := add(ip, 1) + } + case 0x20 { // OP_KECCAK256 + evmGasLeft := chargeGas(evmGasLeft, 30) + + let offset, size + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) + let keccak := keccak256(add(MEM_OFFSET_INNER(), offset), size) + + // When an offset is first accessed (either read or write), memory may trigger + // an expansion, which costs gas. + // dynamicGas = 6 * minimum_word_size + memory_expansion_cost + // minimum_word_size = (size + 31) / 32 + let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + sp := pushStackItem(sp, keccak, evmGasLeft) + ip := add(ip, 1) + } + case 0x30 { // OP_ADDRESS + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, address(), evmGasLeft) + ip := add(ip, 1) + } + case 0x31 { // OP_BALANCE + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr + + addr, sp := popStackItem(sp, evmGasLeft) + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + evmGasLeft := chargeGas(evmGasLeft, 2500) + } + + sp := pushStackItemWithoutCheck(sp, balance(addr)) + ip := add(ip, 1) + } + case 0x32 { // OP_ORIGIN + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, origin(), evmGasLeft) + ip := add(ip, 1) + } + case 0x33 { // OP_CALLER + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, caller(), evmGasLeft) + ip := add(ip, 1) + } + case 0x34 { // OP_CALLVALUE + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, callvalue(), evmGasLeft) + ip := add(ip, 1) + } + case 0x35 { // OP_CALLDATALOAD + evmGasLeft := chargeGas(evmGasLeft, 3) + + let i + + popStackCheck(sp, evmGasLeft, 1) + i, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, calldataload(i)) + ip := add(ip, 1) + } + case 0x36 { // OP_CALLDATASIZE + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, calldatasize(), evmGasLeft) + ip := add(ip, 1) + } + case 0x37 { // OP_CALLDATACOPY + evmGasLeft := chargeGas(evmGasLeft, 3) + + let destOffset, offset, size + + popStackCheck(sp, evmGasLeft, 3) + destOffset, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkMultipleOverflow(offset,size,MEM_OFFSET_INNER(), evmGasLeft) + checkMultipleOverflow(destOffset,size,MEM_OFFSET_INNER(), evmGasLeft) + + // TODO invalid? + if or(gt(add(add(offset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM()), gt(add(add(destOffset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM())) { + $llvm_AlwaysInline_llvm$_memsetToZero(add(destOffset, MEM_OFFSET_INNER()), size) + } + + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + // minimum_word_size = (size + 31) / 32 + let dynamicGas := add(mul(3, shr(5, add(size, 31))), expandMemory(add(destOffset, size))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + calldatacopy(add(destOffset, MEM_OFFSET_INNER()), offset, size) + ip := add(ip, 1) + + } + case 0x38 { // OP_CODESIZE + evmGasLeft := chargeGas(evmGasLeft, 2) + + let bytecodeLen := mload(BYTECODE_OFFSET()) + sp := pushStackItem(sp, bytecodeLen, evmGasLeft) + ip := add(ip, 1) + } + case 0x39 { // OP_CODECOPY + + evmGasLeft := chargeGas(evmGasLeft, 3) + + let dst, offset, len + + popStackCheck(sp, evmGasLeft, 3) + dst, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + len, sp := popStackItemWithoutCheck(sp) + + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + // minimum_word_size = (size + 31) / 32 + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dst, len))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + dst := add(dst, MEM_OFFSET_INNER()) + offset := add(add(offset, BYTECODE_OFFSET()), 32) + + checkOverflow(dst,len, evmGasLeft) + checkMemOverflow(add(dst, len), evmGasLeft) + // Check bytecode overflow + if gt(add(offset, len), sub(MEM_OFFSET(), 1)) { + revertWithGas(evmGasLeft) + } + + $llvm_AlwaysInline_llvm$_memcpy(dst, offset, len) + ip := add(ip, 1) + } + case 0x3A { // OP_GASPRICE + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, gasprice(), evmGasLeft) + ip := add(ip, 1) + } + case 0x3B { // OP_EXTCODESIZE + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr + addr, sp := popStackItem(sp, evmGasLeft) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + evmGasLeft := chargeGas(evmGasLeft, 2500) + } + + sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) + ip := add(ip, 1) + } + case 0x3C { // OP_EXTCODECOPY + evmGasLeft, sp := performExtCodeCopy(evmGasLeft, sp) + ip := add(ip, 1) + } + case 0x3D { // OP_RETURNDATASIZE + evmGasLeft := chargeGas(evmGasLeft, 2) + + let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) + sp := pushStackItem(sp, rdz, evmGasLeft) + ip := add(ip, 1) + } + case 0x3E { // OP_RETURNDATACOPY + evmGasLeft := chargeGas(evmGasLeft, 3) + + let dest, offset, len + popStackCheck(sp, evmGasLeft, 3) + dest, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + len, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset,len, evmGasLeft) + if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { + revertWithGas(evmGasLeft) + } + + // minimum_word_size = (size + 31) / 32 + // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + checkMemOverflowByOffset(offset, evmGasLeft) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dest, len))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + copyActivePtrData(add(MEM_OFFSET_INNER(), dest), offset, len) + ip := add(ip, 1) + } + case 0x3F { // OP_EXTCODEHASH + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr + addr, sp := popStackItem(sp, evmGasLeft) + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + evmGasLeft := chargeGas(evmGasLeft, 2500) + } + + ip := add(ip, 1) + if iszero(addr) { + sp := pushStackItemWithoutCheck(sp, 0) + continue + } + sp := pushStackItemWithoutCheck(sp, extcodehash(addr)) + } + case 0x40 { // OP_BLOCKHASH + evmGasLeft := chargeGas(evmGasLeft, 20) + + let blockNumber + popStackCheck(sp, evmGasLeft, 1) + blockNumber, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, blockhash(blockNumber)) + ip := add(ip, 1) + } + case 0x41 { // OP_COINBASE + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, coinbase(), evmGasLeft) + ip := add(ip, 1) + } + case 0x42 { // OP_TIMESTAMP + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, timestamp(), evmGasLeft) + ip := add(ip, 1) + } + case 0x43 { // OP_NUMBER + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, number(), evmGasLeft) + ip := add(ip, 1) + } + case 0x44 { // OP_PREVRANDAO + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, prevrandao(), evmGasLeft) + ip := add(ip, 1) + } + case 0x45 { // OP_GASLIMIT + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, gaslimit(), evmGasLeft) + ip := add(ip, 1) + } + case 0x46 { // OP_CHAINID + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, chainid(), evmGasLeft) + ip := add(ip, 1) + } + case 0x47 { // OP_SELFBALANCE + evmGasLeft := chargeGas(evmGasLeft, 5) + sp := pushStackItem(sp, selfbalance(), evmGasLeft) + ip := add(ip, 1) + } + case 0x48 { // OP_BASEFEE + evmGasLeft := chargeGas(evmGasLeft, 2) + sp := pushStackItem(sp, basefee(), evmGasLeft) + ip := add(ip, 1) + } + case 0x50 { // OP_POP + evmGasLeft := chargeGas(evmGasLeft, 2) + + let _y + + _y, sp := popStackItem(sp, evmGasLeft) + ip := add(ip, 1) + } + case 0x51 { // OP_MLOAD + evmGasLeft := chargeGas(evmGasLeft, 3) + + let offset + + offset, sp := popStackItem(sp, evmGasLeft) + + checkMemOverflowByOffset(offset, evmGasLeft) + let expansionGas := expandMemory(add(offset, 32)) + evmGasLeft := chargeGas(evmGasLeft, expansionGas) + + let memValue := mload(add(MEM_OFFSET_INNER(), offset)) + sp := pushStackItemWithoutCheck(sp, memValue) + ip := add(ip, 1) + } + case 0x52 { // OP_MSTORE + evmGasLeft := chargeGas(evmGasLeft, 3) + + let offset, value + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + checkMemOverflowByOffset(offset, evmGasLeft) + let expansionGas := expandMemory(add(offset, 32)) + evmGasLeft := chargeGas(evmGasLeft, expansionGas) + + mstore(add(MEM_OFFSET_INNER(), offset), value) + ip := add(ip, 1) + } + case 0x53 { // OP_MSTORE8 + evmGasLeft := chargeGas(evmGasLeft, 3) + + let offset, value + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + checkMemOverflowByOffset(offset, evmGasLeft) + let expansionGas := expandMemory(add(offset, 1)) + evmGasLeft := chargeGas(evmGasLeft, expansionGas) + + mstore8(add(MEM_OFFSET_INNER(), offset), value) + ip := add(ip, 1) + } + case 0x54 { // OP_SLOAD + + evmGasLeft := chargeGas(evmGasLeft, 100) + + let key, value, isWarm + + key, sp := popStackItem(sp, evmGasLeft) + + let wasWarm := isSlotWarm(key) + + if iszero(wasWarm) { + evmGasLeft := chargeGas(evmGasLeft, 2000) + } + + value := sload(key) + + if iszero(wasWarm) { + let _wasW, _orgV := warmSlot(key, value) + } + + sp := pushStackItemWithoutCheck(sp,value) + ip := add(ip, 1) + } + case 0x55 { // OP_SSTORE + evmGasLeft := chargeGas(evmGasLeft, 100) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let key, value, gasSpent + + popStackCheck(sp, evmGasLeft, 2) + key, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + ip := add(ip, 1) + { + // Here it is okay to read before we charge since we known anyway that + // the context has enough funds to compensate at least for the read. + // Im not sure if we need this before: require(gasLeft > GAS_CALL_STIPEND); + let currentValue := sload(key) + let wasWarm, originalValue := warmSlot(key, currentValue) + + if eq(value, currentValue) { + continue + } + + if eq(originalValue, currentValue) { + gasSpent := 19900 + if originalValue { + gasSpent := 2800 + } + } + + if iszero(wasWarm) { + gasSpent := add(gasSpent, 2100) + } + } + + evmGasLeft := chargeGas(evmGasLeft, gasSpent) + sstore(key, value) + + } + // NOTE: We don't currently do full jumpdest validation + // (i.e. validating a jumpdest isn't in PUSH data) + case 0x56 { // OP_JUMP + evmGasLeft := chargeGas(evmGasLeft, 8) + + let counter + + counter, sp := popStackItem(sp, evmGasLeft) + + ip := add(add(BYTECODE_OFFSET(), 32), counter) + + // Check next opcode is JUMPDEST + let nextOpcode := readIP(ip,maxAcceptablePos) + if iszero(eq(nextOpcode, 0x5B)) { + revertWithGas(evmGasLeft) + } + + // execute JUMPDEST immediately + evmGasLeft := chargeGas(evmGasLeft, 1) + ip := add(ip, 1) + } + case 0x57 { // OP_JUMPI + evmGasLeft := chargeGas(evmGasLeft, 10) + + let counter, b + + popStackCheck(sp, evmGasLeft, 2) + counter, sp := popStackItemWithoutCheck(sp) + b, sp := popStackItemWithoutCheck(sp) + + if iszero(b) { + ip := add(ip, 1) + continue + } + + ip := add(add(BYTECODE_OFFSET(), 32), counter) + + // Check next opcode is JUMPDEST + let nextOpcode := readIP(ip,maxAcceptablePos) + if iszero(eq(nextOpcode, 0x5B)) { + revertWithGas(evmGasLeft) + } + + // execute JUMPDEST immediately + evmGasLeft := chargeGas(evmGasLeft, 1) + ip := add(ip, 1) + } + case 0x58 { // OP_PC + evmGasLeft := chargeGas(evmGasLeft, 2) + ip := add(ip, 1) + + // PC = ip - 32 (bytecode size) - 1 (current instruction) + sp := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft) + } + case 0x59 { // OP_MSIZE + evmGasLeft := chargeGas(evmGasLeft,2) + + let size + + size := mload(MEM_OFFSET()) + size := shl(5,size) + sp := pushStackItem(sp,size, evmGasLeft) + ip := add(ip, 1) + } + case 0x5A { // OP_GAS + evmGasLeft := chargeGas(evmGasLeft, 2) + + sp := pushStackItem(sp, evmGasLeft, evmGasLeft) + ip := add(ip, 1) + } + case 0x5B { // OP_JUMPDEST + evmGasLeft := chargeGas(evmGasLeft, 1) + ip := add(ip, 1) + } + case 0x5C { // OP_TLOAD + evmGasLeft := chargeGas(evmGasLeft, 100) + + let key + popStackCheck(sp, evmGasLeft, 1) + key, sp := popStackItemWithoutCheck(sp) + + sp := pushStackItemWithoutCheck(sp, tload(key)) + ip := add(ip, 1) + } + case 0x5D { // OP_TSTORE + evmGasLeft := chargeGas(evmGasLeft, 100) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let key, value + popStackCheck(sp, evmGasLeft, 2) + key, sp := popStackItemWithoutCheck(sp) + value, sp := popStackItemWithoutCheck(sp) + + tstore(key, value) + ip := add(ip, 1) + } + case 0x5E { // OP_MCOPY + let destOffset, offset, size + popStackCheck(sp, evmGasLeft, 3) + destOffset, sp := popStackItemWithoutCheck(sp) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + // TODO overflow checks + checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemOverflowByOffset(add(destOffset, size), evmGasLeft) + + expandMemory(add(destOffset, size)) + expandMemory(add(offset, size)) + + mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) + ip := add(ip, 1) + } + case 0x5F { // OP_PUSH0 + evmGasLeft := chargeGas(evmGasLeft, 2) + + let value := 0 + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 1) + } + case 0x60 { // OP_PUSH1 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,1) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 1) + } + case 0x61 { // OP_PUSH2 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,2) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 2) + } + case 0x62 { // OP_PUSH3 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,3) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 3) + } + case 0x63 { // OP_PUSH4 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,4) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 4) + } + case 0x64 { // OP_PUSH5 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,5) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 5) + } + case 0x65 { // OP_PUSH6 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,6) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 6) + } + case 0x66 { // OP_PUSH7 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,7) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 7) + } + case 0x67 { // OP_PUSH8 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,8) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 8) + } + case 0x68 { // OP_PUSH9 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,9) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 9) + } + case 0x69 { // OP_PUSH10 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,10) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 10) + } + case 0x6A { // OP_PUSH11 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,11) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 11) + } + case 0x6B { // OP_PUSH12 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,12) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 12) + } + case 0x6C { // OP_PUSH13 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,13) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 13) + } + case 0x6D { // OP_PUSH14 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,14) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 14) + } + case 0x6E { // OP_PUSH15 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,15) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 15) + } + case 0x6F { // OP_PUSH16 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,16) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 16) + } + case 0x70 { // OP_PUSH17 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,17) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 17) + } + case 0x71 { // OP_PUSH18 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,18) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 18) + } + case 0x72 { // OP_PUSH19 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,19) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 19) + } + case 0x73 { // OP_PUSH20 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,20) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 20) + } + case 0x74 { // OP_PUSH21 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,21) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 21) + } + case 0x75 { // OP_PUSH22 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,22) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 22) + } + case 0x76 { // OP_PUSH23 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,23) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 23) + } + case 0x77 { // OP_PUSH24 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,24) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 24) + } + case 0x78 { // OP_PUSH25 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,25) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 25) + } + case 0x79 { // OP_PUSH26 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,26) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 26) + } + case 0x7A { // OP_PUSH27 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,27) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 27) + } + case 0x7B { // OP_PUSH28 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,28) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 28) + } + case 0x7C { // OP_PUSH29 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,29) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 29) + } + case 0x7D { // OP_PUSH30 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,30) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 30) + } + case 0x7E { // OP_PUSH31 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,31) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 31) + } + case 0x7F { // OP_PUSH32 + evmGasLeft := chargeGas(evmGasLeft, 3) + + ip := add(ip, 1) + let value := readBytes(ip,maxAcceptablePos,32) + + sp := pushStackItem(sp, value, evmGasLeft) + ip := add(ip, 32) + } + case 0x80 { // OP_DUP1 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 1) + ip := add(ip, 1) + } + case 0x81 { // OP_DUP2 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 2) + ip := add(ip, 1) + } + case 0x82 { // OP_DUP3 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 3) + ip := add(ip, 1) + } + case 0x83 { // OP_DUP4 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 4) + ip := add(ip, 1) + } + case 0x84 { // OP_DUP5 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 5) + ip := add(ip, 1) + } + case 0x85 { // OP_DUP6 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 6) + ip := add(ip, 1) + } + case 0x86 { // OP_DUP7 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 7) + ip := add(ip, 1) + } + case 0x87 { // OP_DUP8 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 8) + ip := add(ip, 1) + } + case 0x88 { // OP_DUP9 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 9) + ip := add(ip, 1) + } + case 0x89 { // OP_DUP10 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 10) + ip := add(ip, 1) + } + case 0x8A { // OP_DUP11 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 11) + ip := add(ip, 1) + } + case 0x8B { // OP_DUP12 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 12) + ip := add(ip, 1) + } + case 0x8C { // OP_DUP13 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 13) + ip := add(ip, 1) + } + case 0x8D { // OP_DUP14 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 14) + ip := add(ip, 1) + } + case 0x8E { // OP_DUP15 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 15) + ip := add(ip, 1) + } + case 0x8F { // OP_DUP16 + sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 16) + ip := add(ip, 1) + } + case 0x90 { // OP_SWAP1 + evmGasLeft := swapStackItem(sp, evmGasLeft, 1) + ip := add(ip, 1) + } + case 0x91 { // OP_SWAP2 + evmGasLeft := swapStackItem(sp, evmGasLeft, 2) + ip := add(ip, 1) + } + case 0x92 { // OP_SWAP3 + evmGasLeft := swapStackItem(sp, evmGasLeft, 3) + ip := add(ip, 1) + } + case 0x93 { // OP_SWAP4 + evmGasLeft := swapStackItem(sp, evmGasLeft, 4) + ip := add(ip, 1) + } + case 0x94 { // OP_SWAP5 + evmGasLeft := swapStackItem(sp, evmGasLeft, 5) + ip := add(ip, 1) + } + case 0x95 { // OP_SWAP6 + evmGasLeft := swapStackItem(sp, evmGasLeft, 6) + ip := add(ip, 1) + } + case 0x96 { // OP_SWAP7 + evmGasLeft := swapStackItem(sp, evmGasLeft, 7) + ip := add(ip, 1) + } + case 0x97 { // OP_SWAP8 + evmGasLeft := swapStackItem(sp, evmGasLeft, 8) + ip := add(ip, 1) + } + case 0x98 { // OP_SWAP9 + evmGasLeft := swapStackItem(sp, evmGasLeft, 9) + ip := add(ip, 1) + } + case 0x99 { // OP_SWAP10 + evmGasLeft := swapStackItem(sp, evmGasLeft, 10) + ip := add(ip, 1) + } + case 0x9A { // OP_SWAP11 + evmGasLeft := swapStackItem(sp, evmGasLeft, 11) + ip := add(ip, 1) + } + case 0x9B { // OP_SWAP12 + evmGasLeft := swapStackItem(sp, evmGasLeft, 12) + ip := add(ip, 1) + } + case 0x9C { // OP_SWAP13 + evmGasLeft := swapStackItem(sp, evmGasLeft, 13) + ip := add(ip, 1) + } + case 0x9D { // OP_SWAP14 + evmGasLeft := swapStackItem(sp, evmGasLeft, 14) + ip := add(ip, 1) + } + case 0x9E { // OP_SWAP15 + evmGasLeft := swapStackItem(sp, evmGasLeft, 15) + ip := add(ip, 1) + } + case 0x9F { // OP_SWAP16 + evmGasLeft := swapStackItem(sp, evmGasLeft, 16) + ip := add(ip, 1) + } + case 0xA0 { // OP_LOG0 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + log0(add(offset, MEM_OFFSET_INNER()), size) + ip := add(ip, 1) + } + case 0xA1 { // OP_LOG1 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size, topic1 + popStackCheck(sp, evmGasLeft, 3) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + topic1, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 375) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + ip := add(ip, 1) + } + case 0xA2 { // OP_LOG2 + evmGasLeft := chargeGas(evmGasLeft, 375) + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 750) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + { + let topic1, topic2 + popStackCheck(sp, evmGasLeft, 2) + topic1, sp := popStackItemWithoutCheck(sp) + topic2, sp := popStackItemWithoutCheck(sp) + log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) + } + ip := add(ip, 1) + } + case 0xA3 { // OP_LOG3 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 1125) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + { + let topic1, topic2, topic3 + popStackCheck(sp, evmGasLeft, 3) + topic1, sp := popStackItemWithoutCheck(sp) + topic2, sp := popStackItemWithoutCheck(sp) + topic3, sp := popStackItemWithoutCheck(sp) + log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) + } + ip := add(ip, 1) + } + case 0xA4 { // OP_LOG4 + evmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + revertWithGas(evmGasLeft) + } + + let offset, size + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset, size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + dynamicGas := add(dynamicGas, 1500) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + + { + let topic1, topic2, topic3, topic4 + popStackCheck(sp, evmGasLeft, 4) + topic1, sp := popStackItemWithoutCheck(sp) + topic2, sp := popStackItemWithoutCheck(sp) + topic3, sp := popStackItemWithoutCheck(sp) + topic4, sp := popStackItemWithoutCheck(sp) + log4(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3, topic4) + } + ip := add(ip, 1) + } + case 0xF0 { // OP_CREATE + evmGasLeft, sp := performCreate(evmGasLeft, sp, isStatic) + ip := add(ip, 1) + } + case 0xF1 { // OP_CALL + evmGasLeft := chargeGas(evmGasLeft, 100) + + let gasUsed + + // A function was implemented in order to avoid stack depth errors. + gasUsed, sp := performCall(sp, evmGasLeft, isStatic) + + // Check if the following is ok + evmGasLeft := chargeGas(evmGasLeft, gasUsed) + ip := add(ip, 1) + } + case 0xF3 { // OP_RETURN + let offset,size + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + checkOverflow(offset,size, evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + + returnLen := size + checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + returnOffset := add(MEM_OFFSET_INNER(), offset) + break + } + case 0xF4 { // OP_DELEGATECALL + evmGasLeft := chargeGas(evmGasLeft, 100) + + let gasUsed + sp, isStatic, gasUsed := delegateCall(sp, isStatic, evmGasLeft) + + evmGasLeft := chargeGas(evmGasLeft, gasUsed) + ip := add(ip, 1) + } + case 0xF5 { // OP_CREATE2 + let result, addr + evmGasLeft, sp, result, addr := performCreate2(evmGasLeft, sp, isStatic) + switch result + case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } + default { sp := pushStackItem(sp, addr, evmGasLeft) } + ip := add(ip, 1) + } + case 0xFA { // OP_STATICCALL + evmGasLeft := chargeGas(evmGasLeft, 100) + + let gasUsed + gasUsed, sp := performStaticCall(sp,evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft,gasUsed) + ip := add(ip, 1) + } + case 0xFD { // OP_REVERT + let offset,size + + popStackCheck(sp, evmGasLeft, 2) + offset, sp := popStackItemWithoutCheck(sp) + size, sp := popStackItemWithoutCheck(sp) + + // TODO invalid? + ensureAcceptableMemLocation(offset) + ensureAcceptableMemLocation(size) + evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + + offset := add(offset, MEM_OFFSET_INNER()) + offset,size := addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) + + revert(offset,size) + } + case 0xFE { // OP_INVALID + evmGasLeft := 0 + + revertWithGas(evmGasLeft) + } + default { + printString("INVALID OPCODE") + printHex(opcode) + revert(0, 0) + } +} diff --git a/system-contracts/package.json b/system-contracts/package.json index bce80474f..6b2f60beb 100644 --- a/system-contracts/package.json +++ b/system-contracts/package.json @@ -62,6 +62,7 @@ "compile-zasm": "ts-node scripts/compile-zasm.ts", "deploy-preimages": "ts-node scripts/deploy-preimages.ts", "preprocess:bootloader": "rm -rf ./bootloader/build && yarn ts-node scripts/preprocess-bootloader.ts", + "preprocess:interpreter": "rm -f ./contracts/EvmInterpreter.yul && yarn ts-node scripts/preprocess-interpreter.ts", "preprocess:system-contracts": "rm -rf ./contracts-preprocessed && ts-node scripts/preprocess-system-contracts.ts", "verify-on-explorer": "hardhat run scripts/verify-on-explorer.ts", "test": "yarn build:test-system-contracts && hardhat test --network zkSyncTestNode", diff --git a/system-contracts/scripts/preprocess-interpreter.ts b/system-contracts/scripts/preprocess-interpreter.ts new file mode 100644 index 000000000..11ff8748b --- /dev/null +++ b/system-contracts/scripts/preprocess-interpreter.ts @@ -0,0 +1,21 @@ +import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs"; + +/* eslint-disable @typescript-eslint/no-var-requires */ +const preprocess = require("preprocess"); +/* eslint-enable@typescript-eslint/no-var-requires */ + +const OUTPUT_DIR = "contracts/"; + +async function main() { + process.chdir(`${OUTPUT_DIR}`); + const interpreterSource = readFileSync(`EvmInterpreter.template.yul`).toString(); + + console.log("Preprocessing Interpreter"); + const interpreter = preprocess.preprocess(interpreterSource); + + writeFileSync(`EvmInterpreter.yul`, interpreter); + + console.log("Intepreter preprocessing done!"); +} + +main(); From fe5d5f59286b7fb311f25f9207b37dfc3a897e35 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Tue, 10 Sep 2024 14:43:39 -0300 Subject: [PATCH 46/59] Move evm interpreter files for preprocessing to a new directory --- .../EvmInterpreter.template.yul | 0 .../EvmInterpreterFunctions.template.yul | 0 .../EvmInterpreterLoop.template.yul | 0 system-contracts/scripts/preprocess-interpreter.ts | 7 ++++--- 4 files changed, 4 insertions(+), 3 deletions(-) rename system-contracts/{contracts => evm-interpreter}/EvmInterpreter.template.yul (100%) rename system-contracts/{contracts => evm-interpreter}/EvmInterpreterFunctions.template.yul (100%) rename system-contracts/{contracts => evm-interpreter}/EvmInterpreterLoop.template.yul (100%) diff --git a/system-contracts/contracts/EvmInterpreter.template.yul b/system-contracts/evm-interpreter/EvmInterpreter.template.yul similarity index 100% rename from system-contracts/contracts/EvmInterpreter.template.yul rename to system-contracts/evm-interpreter/EvmInterpreter.template.yul diff --git a/system-contracts/contracts/EvmInterpreterFunctions.template.yul b/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul similarity index 100% rename from system-contracts/contracts/EvmInterpreterFunctions.template.yul rename to system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul diff --git a/system-contracts/contracts/EvmInterpreterLoop.template.yul b/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul similarity index 100% rename from system-contracts/contracts/EvmInterpreterLoop.template.yul rename to system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul diff --git a/system-contracts/scripts/preprocess-interpreter.ts b/system-contracts/scripts/preprocess-interpreter.ts index 11ff8748b..644bb11d7 100644 --- a/system-contracts/scripts/preprocess-interpreter.ts +++ b/system-contracts/scripts/preprocess-interpreter.ts @@ -4,16 +4,17 @@ import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs"; const preprocess = require("preprocess"); /* eslint-enable@typescript-eslint/no-var-requires */ -const OUTPUT_DIR = "contracts/"; +const OUTPUT_DIR = "contracts"; +const INPUT_DIR = "evm-interpreter"; async function main() { - process.chdir(`${OUTPUT_DIR}`); + process.chdir(`${INPUT_DIR}`); const interpreterSource = readFileSync(`EvmInterpreter.template.yul`).toString(); console.log("Preprocessing Interpreter"); const interpreter = preprocess.preprocess(interpreterSource); - writeFileSync(`EvmInterpreter.yul`, interpreter); + writeFileSync(`../${OUTPUT_DIR}/EvmInterpreter.yul`, interpreter); console.log("Intepreter preprocessing done!"); } From 4d005d39655da1b888098e843b43cf655bbd68e2 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Tue, 10 Sep 2024 15:19:49 -0300 Subject: [PATCH 47/59] Bring missing system contract changes --- .../contracts/ContractDeployer.sol | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index b002013cf..3b32c7014 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -35,7 +35,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { Deployed } - mapping(address => bytes32) public evmCodeHash; + uint256 constant EVM_HASHES_PREFIX = 1 << 254; uint256 public constructorReturnGas; @@ -51,7 +51,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { uint256 bytecodeLen = uint256(bytes32(paddedNewDeployedCode[:32])); bytes memory trueBytecode = paddedNewDeployedCode[32:32 + bytecodeLen]; - evmCodeHash[msg.sender] = keccak256(trueBytecode); + _setEvmCodeHash(msg.sender, keccak256(trueBytecode)); constructorReturnGas = constructorGasLeft; // ToDO: use efficient call @@ -68,6 +68,10 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _; } + function evmCodeHash(address _address) external view returns (bytes32 _hash) { + _hash = _getEvmCodeHash(_address); + } + /// @notice Returns information about a certain account. function getAccountInfo(address _address) external view returns (AccountInfo memory info) { return accountInfo[_address]; @@ -539,7 +543,23 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } } - require(evmCodeHash[_newAddress] != 0x0, "The code hash must be set after the constructor call"); - emit ContractDeployed(_sender, evmCodeHash[_newAddress], _newAddress); + + bytes32 codeHash = _getEvmCodeHash(_newAddress); + require(codeHash != 0x0, "The code hash must be set after the constructor call"); + emit ContractDeployed(_sender, codeHash, _newAddress); + } + + function _setEvmCodeHash(address _address, bytes32 _hash) internal { + assembly { + let slot := or(EVM_HASHES_PREFIX, _address) + sstore(slot, _hash) + } + } + + function _getEvmCodeHash(address _address) internal view returns (bytes32 _hash) { + assembly { + let slot := or(EVM_HASHES_PREFIX, _address) + _hash := sload(slot) + } } } From 99bcbb4b4152c7bd3ec6574b312b3d30a060c978 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Tue, 10 Sep 2024 15:25:21 -0300 Subject: [PATCH 48/59] Format --- system-contracts/contracts/ContractDeployer.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 3b32c7014..39ce48eb4 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -543,7 +543,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } } - bytes32 codeHash = _getEvmCodeHash(_newAddress); require(codeHash != 0x0, "The code hash must be set after the constructor call"); emit ContractDeployed(_sender, codeHash, _newAddress); From 8aa9cdb9accb88126b4e5f1bfd30917be6dc3a50 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Tue, 10 Sep 2024 15:54:09 -0300 Subject: [PATCH 49/59] Fix lints and codespells --- system-contracts/SystemContractsHashes.json | 8 ++++---- system-contracts/contracts/ContractDeployer.sol | 2 +- system-contracts/scripts/preprocess-interpreter.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 4bc4f9bea..779f00ab2 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -31,8 +31,8 @@ "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x01000765b21f3e93da0beb7987904f82bd64d691146fcd9326735f10ea62e533", - "sourceCodeHash": "0x20d42c32468d61bf57fe2067ba5ebaa70d4060583b339e2df2958e72e7869650" + "bytecodeHash": "0x01000759065941e6d7ebd04e39da2ebe0fabfed0acb1eebdbb6a388bbde4317a", + "sourceCodeHash": "0xd089b964a7ad23bf7e53907a778d592a589b451363a902aeebc14abfe559d94b" }, { "contractName": "Create2Factory", @@ -129,8 +129,8 @@ "contractName": "EvmInterpreter", "bytecodePath": "contracts-preprocessed/artifacts/EvmInterpreter.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmInterpreter.yul", - "bytecodeHash": "0x01000e53aa35d9d19fa99341c2e2901cf93b3668f01569dd5c6ca409c7696b91", - "sourceCodeHash": "0x4e16a8c65c4c5c3124dcfa2871da72a0c15744e524086a8c9dc46d7be164d539" + "bytecodeHash": "0x01000ccb740e2345754450eda583f59b31a346920a22f968dfcfc63feae303ee", + "sourceCodeHash": "0xfc91734d4d37538b19c94be0da51364edd4f6664f0fee383cc2e3b5eeb95336a" }, { "contractName": "CodeOracle", diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 39ce48eb4..848bee0cf 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -35,7 +35,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { Deployed } - uint256 constant EVM_HASHES_PREFIX = 1 << 254; + uint256 private constant EVM_HASHES_PREFIX = 1 << 254; uint256 public constructorReturnGas; diff --git a/system-contracts/scripts/preprocess-interpreter.ts b/system-contracts/scripts/preprocess-interpreter.ts index 644bb11d7..2b9d56e48 100644 --- a/system-contracts/scripts/preprocess-interpreter.ts +++ b/system-contracts/scripts/preprocess-interpreter.ts @@ -1,4 +1,4 @@ -import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs"; +import { writeFileSync, readFileSync } from "fs"; /* eslint-disable @typescript-eslint/no-var-requires */ const preprocess = require("preprocess"); @@ -16,7 +16,7 @@ async function main() { writeFileSync(`../${OUTPUT_DIR}/EvmInterpreter.yul`, interpreter); - console.log("Intepreter preprocessing done!"); + console.log("Interpreter preprocessing done!"); } main(); From e017b4e84e3d6e1ec1e4addcac4db67306f7103f Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Tue, 10 Sep 2024 15:57:53 -0300 Subject: [PATCH 50/59] More lints --- system-contracts/scripts/preprocess-interpreter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system-contracts/scripts/preprocess-interpreter.ts b/system-contracts/scripts/preprocess-interpreter.ts index 2b9d56e48..2b031ab9c 100644 --- a/system-contracts/scripts/preprocess-interpreter.ts +++ b/system-contracts/scripts/preprocess-interpreter.ts @@ -9,7 +9,7 @@ const INPUT_DIR = "evm-interpreter"; async function main() { process.chdir(`${INPUT_DIR}`); - const interpreterSource = readFileSync(`EvmInterpreter.template.yul`).toString(); + const interpreterSource = readFileSync("EvmInterpreter.template.yul").toString(); console.log("Preprocessing Interpreter"); const interpreter = preprocess.preprocess(interpreterSource); From 06712919eee98c9babb0a17cc582b3753aa50cf1 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Tue, 10 Sep 2024 16:04:28 -0300 Subject: [PATCH 51/59] Fix contract hashes --- system-contracts/SystemContractsHashes.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 779f00ab2..9d5a639b2 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -31,8 +31,8 @@ "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x01000759065941e6d7ebd04e39da2ebe0fabfed0acb1eebdbb6a388bbde4317a", - "sourceCodeHash": "0xd089b964a7ad23bf7e53907a778d592a589b451363a902aeebc14abfe559d94b" + "bytecodeHash": "0x010007591deebd1c28aec2f09e01fca7831cf2527b6380075c55a46eb89bb3a4", + "sourceCodeHash": "0x83e503214f41dc6677a100378f48961d459750017fc03dc5b8227c2ddddeba8b" }, { "contractName": "Create2Factory", From 0f1383aef1173d5971a67c9af6811036e8e9bfcd Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Tue, 10 Sep 2024 16:27:46 -0300 Subject: [PATCH 52/59] Fix foundry L1 tests --- l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol index 274c80b32..008a93db4 100644 --- a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol +++ b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol @@ -210,7 +210,7 @@ library Utils { } function getGettersSelectors() public pure returns (bytes4[] memory) { - bytes4[] memory selectors = new bytes4[](30); + bytes4[] memory selectors = new bytes4[](31); selectors[0] = GettersFacet.getVerifier.selector; selectors[1] = GettersFacet.getAdmin.selector; selectors[2] = GettersFacet.getPendingAdmin.selector; From 361d19af8346efde0b53243e29612b15f232459e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Rodr=C3=ADguez=20Chatruc?= <49622509+jrchatruc@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:55:56 -0300 Subject: [PATCH 53/59] Revert fetch deployed code len optimization (#31) * Revert fetch deployed code len optimization * Calculate hashes:fix --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmInterpreter.yul | 52 ++++++++++++------- .../EvmInterpreterFunctions.template.yul | 24 +++++---- .../EvmInterpreterLoop.template.yul | 4 +- 4 files changed, 54 insertions(+), 30 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 9d5a639b2..a27725ce2 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -129,8 +129,8 @@ "contractName": "EvmInterpreter", "bytecodePath": "contracts-preprocessed/artifacts/EvmInterpreter.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmInterpreter.yul", - "bytecodeHash": "0x01000ccb740e2345754450eda583f59b31a346920a22f968dfcfc63feae303ee", - "sourceCodeHash": "0xfc91734d4d37538b19c94be0da51364edd4f6664f0fee383cc2e3b5eeb95336a" + "bytecodeHash": "0x01000cef160515b2631803991c1d49b6b44492406197fb6dc22a8cf05cebd5d5", + "sourceCodeHash": "0x6c1e3d4c2f94342792df4fc671a0929fbb2d5aba1b5e388c70f4dc1ee96cfa74" }, { "contractName": "CodeOracle", diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmInterpreter.yul index 077560eb2..be21b7d12 100644 --- a/system-contracts/contracts/EvmInterpreter.yul +++ b/system-contracts/contracts/EvmInterpreter.yul @@ -346,16 +346,22 @@ object "EVMInterpreter" { function _fetchDeployedCodeLen(addr) -> codeLen { let codeHash := _getRawCodeHash(addr) - switch shr(248, codeHash) + mstore(0, codeHash) + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + + switch iszero(success) case 1 { - // EraVM - let codeLengthInWords := and(shr(224, codeHash), 0xffff) - codeLen := shl(5, codeLengthInWords) // codeLengthInWords * 32 + // The code oracle call can only fail in the case where the contract + // we are querying is the current one executing and it has not yet been + // deployed, i.e., if someone calls codesize (or extcodesize(address())) + // inside the constructor. In that case, code length is zero. + codeLen := 0 } - case 2 { - // EVM - let codeLengthInBytes := and(shr(224, codeHash), 0xffff) - codeLen := codeLengthInBytes + default { + // The first word is the true length of the bytecode + returndatacopy(0, 0, 32) + codeLen := mload(0) } } @@ -2040,7 +2046,9 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) + switch _isEVM(addr) + case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } + default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY @@ -3320,16 +3328,22 @@ object "EVMInterpreter" { function _fetchDeployedCodeLen(addr) -> codeLen { let codeHash := _getRawCodeHash(addr) - switch shr(248, codeHash) + mstore(0, codeHash) + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + + switch iszero(success) case 1 { - // EraVM - let codeLengthInWords := and(shr(224, codeHash), 0xffff) - codeLen := shl(5, codeLengthInWords) // codeLengthInWords * 32 + // The code oracle call can only fail in the case where the contract + // we are querying is the current one executing and it has not yet been + // deployed, i.e., if someone calls codesize (or extcodesize(address())) + // inside the constructor. In that case, code length is zero. + codeLen := 0 } - case 2 { - // EVM - let codeLengthInBytes := and(shr(224, codeHash), 0xffff) - codeLen := codeLengthInBytes + default { + // The first word is the true length of the bytecode + returndatacopy(0, 0, 32) + codeLen := mload(0) } } @@ -5014,7 +5028,9 @@ object "EVMInterpreter" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) + switch _isEVM(addr) + case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } + default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY diff --git a/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul b/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul index f53c079d8..2e3567f82 100644 --- a/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul +++ b/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul @@ -264,16 +264,22 @@ function _fetchDeployedCodeWithDest(addr, _offset, _len, dest) -> codeLen { function _fetchDeployedCodeLen(addr) -> codeLen { let codeHash := _getRawCodeHash(addr) - switch shr(248, codeHash) + mstore(0, codeHash) + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + + switch iszero(success) case 1 { - // EraVM - let codeLengthInWords := and(shr(224, codeHash), 0xffff) - codeLen := shl(5, codeLengthInWords) // codeLengthInWords * 32 - } - case 2 { - // EVM - let codeLengthInBytes := and(shr(224, codeHash), 0xffff) - codeLen := codeLengthInBytes + // The code oracle call can only fail in the case where the contract + // we are querying is the current one executing and it has not yet been + // deployed, i.e., if someone calls codesize (or extcodesize(address())) + // inside the constructor. In that case, code length is zero. + codeLen := 0 + } + default { + // The first word is the true length of the bytecode + returndatacopy(0, 0, 32) + codeLen := mload(0) } } diff --git a/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul b/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul index 5880cd1f4..dc3346988 100644 --- a/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul +++ b/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul @@ -480,7 +480,9 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) + switch _isEVM(addr) + case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } + default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY From 220e983c9a873e52bfc7e52e3576f67922a132cb Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 12 Sep 2024 16:48:22 +0200 Subject: [PATCH 54/59] [EVM-Equivalence-YUL] Optimize EvmGasManager (#30) * Optimize EvmGasManager * Fix typo * Simplify consumeEvmFrame * Update hashes --- system-contracts/SystemContractsHashes.json | 34 ++-- system-contracts/contracts/EvmGasManager.sol | 198 ++++++++++--------- 2 files changed, 117 insertions(+), 115 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index a27725ce2..b7f8725c2 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,49 +3,49 @@ "contractName": "AccountCodeStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x0100008312026f2cfaeeb3a9b626e5317d0952371b67e17e0f018f15ba89cdc2", + "bytecodeHash": "0x01000083020a788800971bd67cb136f0a108af6175f3c8ef6f2d9c310e7d439e", "sourceCodeHash": "0xc92c3beabb281421f2d6dc9e46f9ba83b9d46f55a4c1d6799dbec2f57c92b98a" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010007df7ae2e4ece09fe9cdc03c112be3bb6ecc048a53b1409cfab089f670db", + "bytecodeHash": "0x010007df291657eef85afcf35b92cc543704bbe74310dc6567d38683717cf18c", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004dbc6880547bd7ca3dfd987979e377b0e7d16e51bf0f6b187dad05109f", + "bytecodeHash": "0x0100004d263ac56698c0afa68ee10a8cc421af316b9429e9adad0485e10625d9", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100014f624a3e224929d6b036dbd64e3de4c68ca61d225f48c8222e09477f0f", + "bytecodeHash": "0x0100014fe4942740cf80092ba5cd49830fa5e06990d51a32aa829a344f8bafd1", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010007591deebd1c28aec2f09e01fca7831cf2527b6380075c55a46eb89bb3a4", + "bytecodeHash": "0x01000759870142495cc789f42b27ea071402b9e283385cd5105fd910d58cc171", "sourceCodeHash": "0x83e503214f41dc6677a100378f48961d459750017fc03dc5b8227c2ddddeba8b" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x01000049b107e75dfd4df73357da5e7efe0582849ecfd1583ea8cc415252cdf1", + "bytecodeHash": "0x010000492e5d8c096faae7fcf3cfdb29d5d6004c16e87dc3e96b037a2d029b64", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2", + "bytecodeHash": "0x0100058da8bd884adbce2b6acd828821257f183a76f9727c360a599a86270b0e", "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { @@ -59,63 +59,63 @@ "contractName": "EvmGasManager", "bytecodePath": "artifacts-zk/contracts-preprocessed/EvmGasManager.sol/EvmGasManager.json", "sourceCodePath": "contracts-preprocessed/EvmGasManager.sol", - "bytecodeHash": "0x010001015b890ae21f91d270229a4c3aa6fd6ed6b209a1bd7d64b5accebe07f5", - "sourceCodeHash": "0xea3433435888b4fc1195386adb5bf5ca86ee8e4e1472b0eaeef6e907fd4aae6a" + "bytecodeHash": "0x010000d9847779aa157e1cd7e0288bf2a631bc0a8310096bac63bf6645640a7a", + "sourceCodeHash": "0xe1db868b61a8e46fbbda9beaa40f148822395b17f8b3a33fc77506eb5e9459d0" }, { "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000039194d946e10393e585e587a0fed12a0b67f2a44600c81c0c07bb3e10e", + "bytecodeHash": "0x010000391e2cdad250fd602dff3fcea7870ee223f808ead56a357e8b38055b6e", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cfc53c719b7e5bec45883cf662e9a9099d016fba16bfe03b9e65f2b722", + "bytecodeHash": "0x010000cfc0360ecf7a6e9e8f8ecd9b54ee27385f9b6b232adfddce3d449f0f37", "sourceCodeHash": "0xe07e6543ac09b86042eff5f9067df6db10a4fc039ecb56098a882ee1019c3031" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000299800a4edde1beaefff3e07af2387d0b34f2dfbcdf4ed1d87c0888ae90", + "bytecodeHash": "0x01000299be7537c3834ed927d5312cf76ae2f3e4a767a96c92b453c228956668", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x01000103c7807def7581dcf186b53df739e3b4c5d93b13a96741e7295e2e3f02", + "bytecodeHash": "0x01000103ab63d39452895c83f53c1a7c4b4f95116aeae8a967d16bf2ee09eca7", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005d99f6a76cec4466f3e1f95ee53731a64053035da02b287854a8a6a1a3", + "bytecodeHash": "0x0100005da55171be1d9fe53bc375c3cece09da020b2937bde85149adec4e5ea6", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000d90192a1e931774c502cd530a5e950001e8f6fd8324c3a6767ad473ba9", + "bytecodeHash": "0x010000d99ef515521442da25a1688797f303f837646b83f14d3be3b873b60603", "sourceCodeHash": "0xff1ab1ce15c2e54954077315618822ec8deaeaae79ba4e2899518b8713a7234e" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000047524067c7075952b5ebc383b3848e7a914164db9e7133c436ec2fd00e", + "bytecodeHash": "0x0100004734464645db5a1801d3e7b23db3ce982ef4e0650f782abea9c7d355ec", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a5a7920f9eac0b72744e73310ed60294df349fb9028ef3f5eb2dfab0aa", + "bytecodeHash": "0x010001a5a0ffa6d6f8eed05cf0305b346c93d08ab31950a1f51eef296523e60c", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index 8825bcfa7..c10792842 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -4,84 +4,45 @@ pragma solidity ^0.8.0; +import "./libraries/Utils.sol"; + import {ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "./Constants.sol"; import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; // We consider all the contracts (including system ones) as warm. uint160 constant PRECOMPILES_END = 0xffff; -// Denotes that passGas has been consumed uint256 constant INF_PASS_GAS = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; -contract EvmGasManager { - // We need trust to use `storage` pointers - struct WarmAccountInfo { - bool isWarm; - } - - struct SlotInfo { - bool warm; - uint256 originalValue; - } - - // We dont care about the size, since none of it will be stored/published anyway. - struct EVMStackFrameInfo { - bool isStatic; - uint256 passGas; - } - - // The following storage variables are not used anywhere explicitly and are just used to obtain the storage pointers - // to use the transient storage with. - mapping(address => WarmAccountInfo) private warmAccounts; - mapping(address => mapping(uint256 => SlotInfo)) private warmSlots; - EVMStackFrameInfo[] private evmStackFrames; - - function tstoreWarmAccount(address account, bool isWarm) internal { - WarmAccountInfo storage ptr = warmAccounts[account]; - - assembly { - tstore(ptr.slot, isWarm) - } - } - - function tloadWarmAccount(address account) internal returns (bool isWarm) { - WarmAccountInfo storage ptr = warmAccounts[account]; - - assembly { - isWarm := tload(ptr.slot) - } - } - - function tstoreWarmSlot(address _account, uint256 _key, SlotInfo memory info) internal { - SlotInfo storage ptr = warmSlots[_account][_key]; - - bool warm = info.warm; - uint256 originalValue = info.originalValue; +// Transient storage prefixes +uint256 constant IS_ACCOUNT_EVM_PREFIX = 1 << 255; +uint256 constant IS_ACCOUNT_WARM_PREFIX = 1 << 254; +uint256 constant IS_SLOT_WARM_PREFIX = 1 << 253; +uint256 constant EVM_STACK_SLOT = 2; +contract EvmGasManager { + modifier onlySystemEvm() { + // cache use is safe since we do not support SELFDESTRUCT + uint256 transient_slot = IS_ACCOUNT_EVM_PREFIX | uint256(uint160(msg.sender)); + bool isEVM; assembly { - tstore(ptr.slot, warm) - tstore(add(ptr.slot, 1), originalValue) + isEVM := tload(transient_slot) } - } - - function tloadWarmSlot(address _account, uint256 _key) internal view returns (SlotInfo memory info) { - SlotInfo storage ptr = warmSlots[_account][_key]; - - bool isWarm; - uint256 originalValue; - assembly { - isWarm := tload(ptr.slot) - originalValue := tload(add(ptr.slot, 1)) + if (!isEVM) { + bytes32 bytecodeHash = ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.getRawCodeHash(msg.sender); + isEVM = Utils.isCodeHashEVM(bytecodeHash); + if (isEVM) { + if (!Utils.isContractConstructing(bytecodeHash)) { + assembly { + tstore(transient_slot, isEVM) + } + } + } } - info.warm = isWarm; - info.originalValue = originalValue; - } - - modifier onlySystemEvm() { - require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender), "only system evm"); - require(SystemContractHelper.isSystemCall(), "This method require system call flag"); + require(isEVM, "only system evm"); + require(SystemContractHelper.isSystemCall(), "This method requires system call flag"); _; } @@ -91,64 +52,105 @@ contract EvmGasManager { function warmAccount(address account) external payable onlySystemEvm returns (bool wasWarm) { if (uint160(account) < PRECOMPILES_END) return true; - wasWarm = tloadWarmAccount(account); - if (!wasWarm) tstoreWarmAccount(account, true); - } - - function isSlotWarm(uint256 _slot) external view returns (bool) { - SlotInfo storage ptr = warmSlots[msg.sender][_slot]; - bool isWarm; + uint256 transient_slot = IS_ACCOUNT_WARM_PREFIX | uint256(uint160(account)); assembly { - isWarm := tload(ptr.slot) + wasWarm := tload(transient_slot) } - return isWarm; + if (!wasWarm) { + assembly { + tstore(transient_slot, 1) + } + } } - function warmSlot(uint256 _slot, uint256 _currentValue) external payable onlySystemEvm returns (bool, uint256) { - SlotInfo memory info = tloadWarmSlot(msg.sender, _slot); + function isSlotWarm(uint256 _slot) external view returns (bool isWarm) { + uint256 prefix = IS_SLOT_WARM_PREFIX | uint256(uint160(msg.sender)); + uint256 transient_slot; + assembly { + mstore(0, prefix) + mstore(0x20, _slot) + transient_slot := keccak256(0, 64) + } - if (info.warm) { - return (true, info.originalValue); + assembly { + isWarm := tload(transient_slot) } + } - info.warm = true; - info.originalValue = _currentValue; + function warmSlot( + uint256 _slot, + uint256 _currentValue + ) external payable onlySystemEvm returns (bool isWarm, uint256 originalValue) { + uint256 prefix = IS_SLOT_WARM_PREFIX | uint256(uint160(msg.sender)); + uint256 transient_slot; + assembly { + mstore(0, prefix) + mstore(0x20, _slot) + transient_slot := keccak256(0, 64) + } - tstoreWarmSlot(msg.sender, _slot, info); + assembly { + isWarm := tload(transient_slot) + } - return (false, _currentValue); + if (isWarm) { + assembly { + originalValue := tload(add(transient_slot, 1)) + } + } else { + originalValue = _currentValue; + + assembly { + tstore(transient_slot, 1) + tstore(add(transient_slot, 1), originalValue) + } + } } /* + The flow is the following: + When conducting call: 1. caller calls to an EVM contract pushEVMFrame with the corresponding gas - 2. callee calls consumeEvmFrame to get the gas & make sure that subsequent callee won't be able to read it. - 3. callee sets the return gas - 4. callee calls popEVMFrame to return the gas to the caller & remove the frame + 2. callee calls consumeEvmFrame to get the gas and determine if a call is static + 3. calleer calls popEVMFrame to remove the frame */ - function pushEVMFrame(uint256 _passGas, bool _isStatic) external onlySystemEvm { - EVMStackFrameInfo memory frame = EVMStackFrameInfo({passGas: _passGas, isStatic: _isStatic}); - - evmStackFrames.push(frame); + function pushEVMFrame(uint256 passGas, bool isStatic) external onlySystemEvm { + assembly { + let stackDepth := add(tload(EVM_STACK_SLOT), 1) + tstore(EVM_STACK_SLOT, stackDepth) + let stackPointer := add(EVM_STACK_SLOT, mul(2, stackDepth)) + tstore(stackPointer, passGas) + tstore(add(stackPointer, 1), isStatic) + } } - function consumeEvmFrame() external onlySystemEvm returns (uint256 passGas, bool isStatic) { - if (evmStackFrames.length == 0) return (INF_PASS_GAS, false); - - EVMStackFrameInfo memory frameInfo = evmStackFrames[evmStackFrames.length - 1]; - - passGas = frameInfo.passGas; - isStatic = frameInfo.isStatic; + function consumeEvmFrame() external view returns (uint256 passGas, bool isStatic) { + uint256 stackDepth; + assembly { + stackDepth := tload(EVM_STACK_SLOT) + } + if (stackDepth == 0) return (INF_PASS_GAS, false); - // Mark as used - evmStackFrames[evmStackFrames.length - 1].passGas = INF_PASS_GAS; + assembly { + let stackPointer := add(EVM_STACK_SLOT, mul(2, stackDepth)) + passGas := tload(stackPointer) + isStatic := tload(add(stackPointer, 1)) + } } function popEVMFrame() external onlySystemEvm { - evmStackFrames.pop(); + uint256 stackDepth; + assembly { + stackDepth := tload(EVM_STACK_SLOT) + } + require(stackDepth != 0); + assembly { + tstore(EVM_STACK_SLOT, sub(stackDepth, 1)) + } } } From 32c05a16ed072a04bfb7b0928c3cf219dadd2727 Mon Sep 17 00:00:00 2001 From: Nacho Avecilla Date: Fri, 13 Sep 2024 13:46:58 -0300 Subject: [PATCH 55/59] [EVM-Equivalence-YUL] Fix overflow checks (#29) * Remove invalid todos adding overflow checks * Remove old memory check * Add preprocessed evm interpreter * Remove unnecesary memory checks * Update hash for evm interpreter --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmInterpreter.yul | 60 ++++++++----------- .../EvmInterpreterFunctions.template.yul | 6 -- .../EvmInterpreterLoop.template.yul | 24 ++++---- 4 files changed, 38 insertions(+), 56 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index b7f8725c2..c7357d0c1 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -129,8 +129,8 @@ "contractName": "EvmInterpreter", "bytecodePath": "contracts-preprocessed/artifacts/EvmInterpreter.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmInterpreter.yul", - "bytecodeHash": "0x01000cef160515b2631803991c1d49b6b44492406197fb6dc22a8cf05cebd5d5", - "sourceCodeHash": "0x6c1e3d4c2f94342792df4fc671a0929fbb2d5aba1b5e388c70f4dc1ee96cfa74" + "bytecodeHash": "0x01000cdf5bb7dd8a97faf231a5e1e20f2fe308d6f200c3295c6e3629547cc4a4", + "sourceCodeHash": "0xe1133c2af9e4fc38e845f7fcc23f3cbab37b857013f55b6e7e9bdea28f331c40" }, { "contractName": "CodeOracle", diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmInterpreter.yul index be21b7d12..dca506aab 100644 --- a/system-contracts/contracts/EvmInterpreter.yul +++ b/system-contracts/contracts/EvmInterpreter.yul @@ -747,12 +747,6 @@ object "EVMInterpreter" { ret := farCallAbi } - function ensureAcceptableMemLocation(location) { - if gt(location,MAX_POSSIBLE_MEM()) { - revert(0,0) // Check if this is what's needed - } - } - function addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) -> newOffset,newSize { newOffset := offset newSize := size @@ -1976,13 +1970,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset,size,MEM_OFFSET_INNER(), evmGasLeft) - checkMultipleOverflow(destOffset,size,MEM_OFFSET_INNER(), evmGasLeft) - - // TODO invalid? - if or(gt(add(add(offset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM()), gt(add(add(destOffset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM())) { - $llvm_AlwaysInline_llvm$_memsetToZero(add(destOffset, MEM_OFFSET_INNER()), size) - } + checkOverflow(destOffset, size, evmGasLeft) + checkMemOverflowByOffset(add(destOffset,size), evmGasLeft) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -2020,6 +2009,7 @@ object "EVMInterpreter" { offset := add(add(offset, BYTECODE_OFFSET()), 32) checkOverflow(dst,len, evmGasLeft) + checkOverflow(offset,len, evmGasLeft) checkMemOverflow(add(dst, len), evmGasLeft) // Check bytecode overflow if gt(add(offset, len), sub(MEM_OFFSET(), 1)) { @@ -2378,7 +2368,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - // TODO overflow checks + checkOverflow(offset, size, evmGasLeft) + checkOverflow(destOffset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) checkMemOverflowByOffset(add(destOffset, size), evmGasLeft) @@ -2971,10 +2962,12 @@ object "EVMInterpreter" { size, sp := popStackItemWithoutCheck(sp) checkOverflow(offset,size, evmGasLeft) + checkMemOverflowByOffset(add(offset,size), evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) returnLen := size - checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + + // Don't check overflow here since previous checks are enough to ensure this is safe returnOffset := add(MEM_OFFSET_INNER(), offset) break } @@ -3010,11 +3003,12 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - // TODO invalid? - ensureAcceptableMemLocation(offset) - ensureAcceptableMemLocation(size) + checkOverflow(offset,size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + + // Don't check overflow here since previous checks are enough to ensure this is safe offset := add(offset, MEM_OFFSET_INNER()) offset,size := addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) @@ -3729,12 +3723,6 @@ object "EVMInterpreter" { ret := farCallAbi } - function ensureAcceptableMemLocation(location) { - if gt(location,MAX_POSSIBLE_MEM()) { - revert(0,0) // Check if this is what's needed - } - } - function addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) -> newOffset,newSize { newOffset := offset newSize := size @@ -4958,13 +4946,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset,size,MEM_OFFSET_INNER(), evmGasLeft) - checkMultipleOverflow(destOffset,size,MEM_OFFSET_INNER(), evmGasLeft) - - // TODO invalid? - if or(gt(add(add(offset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM()), gt(add(add(destOffset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM())) { - $llvm_AlwaysInline_llvm$_memsetToZero(add(destOffset, MEM_OFFSET_INNER()), size) - } + checkOverflow(destOffset, size, evmGasLeft) + checkMemOverflowByOffset(add(destOffset,size), evmGasLeft) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -5002,6 +4985,7 @@ object "EVMInterpreter" { offset := add(add(offset, BYTECODE_OFFSET()), 32) checkOverflow(dst,len, evmGasLeft) + checkOverflow(offset,len, evmGasLeft) checkMemOverflow(add(dst, len), evmGasLeft) // Check bytecode overflow if gt(add(offset, len), sub(MEM_OFFSET(), 1)) { @@ -5360,7 +5344,8 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - // TODO overflow checks + checkOverflow(offset, size, evmGasLeft) + checkOverflow(destOffset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) checkMemOverflowByOffset(add(destOffset, size), evmGasLeft) @@ -5953,10 +5938,12 @@ object "EVMInterpreter" { size, sp := popStackItemWithoutCheck(sp) checkOverflow(offset,size, evmGasLeft) + checkMemOverflowByOffset(add(offset,size), evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) returnLen := size - checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + + // Don't check overflow here since previous checks are enough to ensure this is safe returnOffset := add(MEM_OFFSET_INNER(), offset) break } @@ -5992,11 +5979,12 @@ object "EVMInterpreter" { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - // TODO invalid? - ensureAcceptableMemLocation(offset) - ensureAcceptableMemLocation(size) + checkOverflow(offset,size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + + // Don't check overflow here since previous checks are enough to ensure this is safe offset := add(offset, MEM_OFFSET_INNER()) offset,size := addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) diff --git a/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul b/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul index 2e3567f82..f600df165 100644 --- a/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul +++ b/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul @@ -665,12 +665,6 @@ function getFarCallABI( ret := farCallAbi } -function ensureAcceptableMemLocation(location) { - if gt(location,MAX_POSSIBLE_MEM()) { - revert(0,0) // Check if this is what's needed - } -} - function addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) -> newOffset,newSize { newOffset := offset newSize := size diff --git a/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul b/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul index dc3346988..eb2cac4ec 100644 --- a/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul +++ b/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul @@ -410,13 +410,8 @@ for { } true { } { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - checkMultipleOverflow(offset,size,MEM_OFFSET_INNER(), evmGasLeft) - checkMultipleOverflow(destOffset,size,MEM_OFFSET_INNER(), evmGasLeft) - - // TODO invalid? - if or(gt(add(add(offset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM()), gt(add(add(destOffset, size), MEM_OFFSET_INNER()), MAX_POSSIBLE_MEM())) { - $llvm_AlwaysInline_llvm$_memsetToZero(add(destOffset, MEM_OFFSET_INNER()), size) - } + checkOverflow(destOffset, size, evmGasLeft) + checkMemOverflowByOffset(add(destOffset,size), evmGasLeft) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -454,6 +449,7 @@ for { } true { } { offset := add(add(offset, BYTECODE_OFFSET()), 32) checkOverflow(dst,len, evmGasLeft) + checkOverflow(offset,len, evmGasLeft) checkMemOverflow(add(dst, len), evmGasLeft) // Check bytecode overflow if gt(add(offset, len), sub(MEM_OFFSET(), 1)) { @@ -812,7 +808,8 @@ for { } true { } { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - // TODO overflow checks + checkOverflow(offset, size, evmGasLeft) + checkOverflow(destOffset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) checkMemOverflowByOffset(add(destOffset, size), evmGasLeft) @@ -1405,10 +1402,12 @@ for { } true { } { size, sp := popStackItemWithoutCheck(sp) checkOverflow(offset,size, evmGasLeft) + checkMemOverflowByOffset(add(offset,size), evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) returnLen := size - checkOverflow(offset,MEM_OFFSET_INNER(), evmGasLeft) + + // Don't check overflow here since previous checks are enough to ensure this is safe returnOffset := add(MEM_OFFSET_INNER(), offset) break } @@ -1444,11 +1443,12 @@ for { } true { } { offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - // TODO invalid? - ensureAcceptableMemLocation(offset) - ensureAcceptableMemLocation(size) + checkOverflow(offset,size, evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + + // Don't check overflow here since previous checks are enough to ensure this is safe offset := add(offset, MEM_OFFSET_INNER()) offset,size := addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) From 172240266b7f6fe572e768224dae44a96517dbf8 Mon Sep 17 00:00:00 2001 From: IAvecilla Date: Mon, 16 Sep 2024 10:42:24 -0300 Subject: [PATCH 56/59] Fix l1 hardhat test adding evm simulator code hash --- l1-contracts/test/unit_tests/executor_proof.spec.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/l1-contracts/test/unit_tests/executor_proof.spec.ts b/l1-contracts/test/unit_tests/executor_proof.spec.ts index 01ac20fc7..8bbb46df3 100644 --- a/l1-contracts/test/unit_tests/executor_proof.spec.ts +++ b/l1-contracts/test/unit_tests/executor_proof.spec.ts @@ -15,9 +15,11 @@ describe("Executor test", function () { /// This test is based on a block generated in a local system. it("Test hashes (Rollup)", async () => { - const bootloaderHash = "0x010009416e909e0819593a9806bbc841d25c5cdfed3f4a1523497c6814e5194a"; - const aaHash = "0x0100065d134a862a777e50059f5e0fbe68b583f3617a67820f7edda0d7f253a0"; - const setResult = await executor.setHashes(aaHash, bootloaderHash); + const bootloaderHash = "0x010008bbde6fc402ea3a3d6cb15cb97e70245d3d4e48fb74362d4961b74c16b1"; + const aaHash = "0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2"; + const evmSimulatorHash = "0x01000ccb740e2345754450eda583f59b31a346920a22f968dfcfc63feae303ee"; + + const setResult = await executor.setHashes(aaHash, bootloaderHash, evmSimulatorHash); const finish = await setResult.wait(); expect(finish.status == 1); From 2edbd6912c6a73b120377f5e53fe1cc5343407fc Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 17 Sep 2024 16:43:50 +0200 Subject: [PATCH 57/59] fix: Revert consumeEvmFrame EvmGasManager optimization (#32) * Revert consumeEvmFrame EvmGasManager optimization * Update hashes --- system-contracts/SystemContractsHashes.json | 34 ++++++++++---------- system-contracts/contracts/EvmGasManager.sol | 3 +- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index c7357d0c1..2f0d9d00f 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,49 +3,49 @@ "contractName": "AccountCodeStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x01000083020a788800971bd67cb136f0a108af6175f3c8ef6f2d9c310e7d439e", + "bytecodeHash": "0x0100008316f1f5fba0ee0278c40250b93c59fb5edb75658bfd2d3eb59e46fc2e", "sourceCodeHash": "0xc92c3beabb281421f2d6dc9e46f9ba83b9d46f55a4c1d6799dbec2f57c92b98a" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010007df291657eef85afcf35b92cc543704bbe74310dc6567d38683717cf18c", + "bytecodeHash": "0x010007df001042752bef1c06161539a67ddc09461f32c8ed33402739e75b5787", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004d263ac56698c0afa68ee10a8cc421af316b9429e9adad0485e10625d9", + "bytecodeHash": "0x0100004dd0d550356d61d5735f7eef2fc8658aebe72e236058242d08615f4840", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100014fe4942740cf80092ba5cd49830fa5e06990d51a32aa829a344f8bafd1", + "bytecodeHash": "0x0100014f5d4ca4d3f10878213fdec3f6cecaa7ad5738385a5047084175690013", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x01000759870142495cc789f42b27ea071402b9e283385cd5105fd910d58cc171", + "bytecodeHash": "0x0100075982594cce9610e02a1043cf1bc0c9163045e646ac5b91534708f1dc2e", "sourceCodeHash": "0x83e503214f41dc6677a100378f48961d459750017fc03dc5b8227c2ddddeba8b" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x010000492e5d8c096faae7fcf3cfdb29d5d6004c16e87dc3e96b037a2d029b64", + "bytecodeHash": "0x01000049d9a335e68cabc6be9103b1ce5bb12bc061eb9174105eaa4a03f6a2b3", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100058da8bd884adbce2b6acd828821257f183a76f9727c360a599a86270b0e", + "bytecodeHash": "0x0100058de8a8fda78449f14bece247271bdbba5dc73fc96135c35a17ee4dd090", "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { @@ -59,63 +59,63 @@ "contractName": "EvmGasManager", "bytecodePath": "artifacts-zk/contracts-preprocessed/EvmGasManager.sol/EvmGasManager.json", "sourceCodePath": "contracts-preprocessed/EvmGasManager.sol", - "bytecodeHash": "0x010000d9847779aa157e1cd7e0288bf2a631bc0a8310096bac63bf6645640a7a", - "sourceCodeHash": "0xe1db868b61a8e46fbbda9beaa40f148822395b17f8b3a33fc77506eb5e9459d0" + "bytecodeHash": "0x010000f9b3ed54d84d89d5b3088afc18abe188a0834a8f0753a4e9997fd53224", + "sourceCodeHash": "0x0af32498e20adb67fd8e1af9d47679757379793ec3330b93cf0d8726ca9e0b2a" }, { "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x010000391e2cdad250fd602dff3fcea7870ee223f808ead56a357e8b38055b6e", + "bytecodeHash": "0x01000039220b93fa1579ef897a360af9528e8b2b9f11ee24a836e07f9869879d", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cfc0360ecf7a6e9e8f8ecd9b54ee27385f9b6b232adfddce3d449f0f37", + "bytecodeHash": "0x010000cfaa9edbf2c7a4ee998090c0b7f78865f3df19811221a2d814a2eed9bb", "sourceCodeHash": "0xe07e6543ac09b86042eff5f9067df6db10a4fc039ecb56098a882ee1019c3031" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000299be7537c3834ed927d5312cf76ae2f3e4a767a96c92b453c228956668", + "bytecodeHash": "0x01000299cba1a466f8bf47bfb8e08a2fa82910f0b47dbb0c7ecc21722c6b9627", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x01000103ab63d39452895c83f53c1a7c4b4f95116aeae8a967d16bf2ee09eca7", + "bytecodeHash": "0x01000103fb54b518a2f4f51a2831d1f15e5bacc93e1ae0c65220a78a7c1f9231", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005da55171be1d9fe53bc375c3cece09da020b2937bde85149adec4e5ea6", + "bytecodeHash": "0x0100005ded615ffb3639db7834b9aa49fbd2380fb63e3d5edff7de979d659d7c", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000d99ef515521442da25a1688797f303f837646b83f14d3be3b873b60603", + "bytecodeHash": "0x010000d9db21a9ac5d34d5e70fb3fd9fd65a51df6f38abb18bfaa29e90600def", "sourceCodeHash": "0xff1ab1ce15c2e54954077315618822ec8deaeaae79ba4e2899518b8713a7234e" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x0100004734464645db5a1801d3e7b23db3ce982ef4e0650f782abea9c7d355ec", + "bytecodeHash": "0x0100004714b937ae2caf106ea1ce6c641c0e7d49076b9a9f3124d3a6249c841a", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a5a0ffa6d6f8eed05cf0305b346c93d08ab31950a1f51eef296523e60c", + "bytecodeHash": "0x010001a5edef8985cb8bf31be024c56392e8a52d42162b12656178ad4450c02d", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index c10792842..398735247 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -129,7 +129,7 @@ contract EvmGasManager { } } - function consumeEvmFrame() external view returns (uint256 passGas, bool isStatic) { + function consumeEvmFrame() external onlySystemEvm returns (uint256 passGas, bool isStatic) { uint256 stackDepth; assembly { stackDepth := tload(EVM_STACK_SLOT) @@ -140,6 +140,7 @@ contract EvmGasManager { let stackPointer := add(EVM_STACK_SLOT, mul(2, stackDepth)) passGas := tload(stackPointer) isStatic := tload(add(stackPointer, 1)) + tstore(stackPointer, INF_PASS_GAS) // mark as consumed } } From 62e0e046daa2f99a509b5c6c908f17e1f7ff8ca0 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 24 Sep 2024 01:43:11 +0200 Subject: [PATCH 58/59] chore: Initial cleanup in EvmInterpreter (#33) * Cleanup EvmInterpreterFunctions * Cleanup in logs * Remove unneded changes * Use rawMimicCall --- system-contracts/contracts/Constants.sol | 4 +- .../contracts/ContractDeployer.sol | 16 +- system-contracts/contracts/EvmInterpreter.yul | 336 +++--------------- system-contracts/contracts/NonceHolder.sol | 2 - .../interfaces/IContractDeployer.sol | 2 - .../contracts/interfaces/IEvmGasManager.sol | 25 -- .../libraries/SystemContractHelper.sol | 36 -- .../contracts/libraries/Utils.sol | 2 - .../EvmInterpreterFunctions.template.yul | 150 ++------ .../EvmInterpreterLoop.template.yul | 18 +- 10 files changed, 98 insertions(+), 493 deletions(-) diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index 2bfdcc8bd..dab28bfdc 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -14,7 +14,7 @@ import {ICompressor} from "./interfaces/ICompressor.sol"; import {IComplexUpgrader} from "./interfaces/IComplexUpgrader.sol"; import {IBootloaderUtilities} from "./interfaces/IBootloaderUtilities.sol"; import {IPubdataChunkPublisher} from "./interfaces/IPubdataChunkPublisher.sol"; -import "./EvmGasManager.sol"; +import {IEvmGasManager} from "./interfaces/IEvmGasManager.sol"; /// @dev All the system contracts introduced by ZKsync have their addresses /// started from 2^15 in order to avoid collision with Ethereum precompiles. @@ -85,7 +85,7 @@ address constant EVENT_WRITER_CONTRACT = address(SYSTEM_CONTRACTS_OFFSET + 0x0d) ICompressor constant COMPRESSOR_CONTRACT = ICompressor(address(SYSTEM_CONTRACTS_OFFSET + 0x0e)); IComplexUpgrader constant COMPLEX_UPGRADER_CONTRACT = IComplexUpgrader(address(SYSTEM_CONTRACTS_OFFSET + 0x0f)); -EvmGasManager constant EVM_GAS_MANAGER = EvmGasManager(address(SYSTEM_CONTRACTS_OFFSET + 0x13)); +IEvmGasManager constant EVM_GAS_MANAGER = IEvmGasManager(address(SYSTEM_CONTRACTS_OFFSET + 0x13)); IPubdataChunkPublisher constant PUBDATA_CHUNK_PUBLISHER = IPubdataChunkPublisher( address(SYSTEM_CONTRACTS_OFFSET + 0x11) diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 848bee0cf..15656eda8 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -532,15 +532,17 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { SystemContractHelper.setValueForNextFarCall(uint128(value)); } - // In case of EVM contracts returnData is the new deployed code - bool success = SystemContractHelper.mimicCall(uint32(gasleft()), _newAddress, msg.sender, _input, true, false); + bool success = EfficientCall.rawMimicCall({ + _gas: uint32(gasleft()), + _address: _newAddress, + _data: _input, + _whoToMimic: msg.sender, + _isConstructor: true, + _isSystem: false + }); if (!success) { - assembly { - // Just propagate the error back - returndatacopy(0, 0, returndatasize()) - revert(0, returndatasize()) - } + EfficientCall.propagateRevert(); } bytes32 codeHash = _getEvmCodeHash(_newAddress); diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmInterpreter.yul index dca506aab..b16daad6a 100644 --- a/system-contracts/contracts/EvmInterpreter.yul +++ b/system-contracts/contracts/EvmInterpreter.yul @@ -80,10 +80,6 @@ object "EVMInterpreter" { returnGas := chargeGas(gasToReturn, gasForCode) } - function SYSTEM_CONTRACTS_OFFSET() -> offset { - offset := 0x8000 - } - function ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008002 } @@ -96,10 +92,6 @@ object "EVMInterpreter" { addr := 0x0000000000000000000000000000000000008006 } - function CODE_ADDRESS_CALL_ADDRESS() -> addr { - addr := 0x000000000000000000000000000000000000FFFE - } - function CODE_ORACLE_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008012 } @@ -108,12 +100,8 @@ object "EVMInterpreter" { addr := 0x0000000000000000000000000000000000008013 } - function CALLFLAGS_CALL_ADDRESS() -> addr { - addr := 0x000000000000000000000000000000000000FFEF - } - function DEBUG_SLOT_OFFSET() -> offset { - offset := mul(32, 32) + offset := mul(32, 32) // TODO cleanup } function LAST_RETURNDATA_SIZE_OFFSET() -> offset { @@ -156,6 +144,25 @@ object "EVMInterpreter" { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } + // Essentially a NOP that will not get optimized away by the compiler + function $llvm_NoInline_llvm$_unoptimized() { + pop(1) + } + + function printHex(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebde) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() + } + + function printString(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdf) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() + } + // It is the responsibility of the caller to ensure that ip >= BYTECODE_OFFSET + 32 function readIP(ip,maxAcceptablePos) -> opcode { if gt(ip, maxAcceptablePos) { @@ -293,21 +300,6 @@ object "EVMInterpreter" { hash := mload(0) } - function _getCodeHash(account) -> hash { - // function getCodeHash(uint256 _input) external view override returns (bytes32) - mstore(0, 0xE03FE17700000000000000000000000000000000000000000000000000000000) - mstore(4, account) - - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - hash := mload(0) - } - function getIsStaticFromCallFlags() -> isStatic { isStatic := verbatim_0i_1o("get_global::call_flags") isStatic := iszero(iszero(and(isStatic, 0x04))) @@ -424,13 +416,6 @@ object "EVMInterpreter" { } } - function getMin(a, b) -> min { - min := b - if lt(a, b) { - min := a - } - } - function bitLength(n) -> bitLen { for { } gt(n, 0) { } { // while(n > 0) if iszero(n) { @@ -586,13 +571,6 @@ object "EVMInterpreter" { } } - function checkMultipleOverflow(data1, data2, data3, evmGasLeft) { - checkOverflow(data1, data2, evmGasLeft) - checkOverflow(data1, data3, evmGasLeft) - checkOverflow(data2, data3, evmGasLeft) - checkOverflow(add(data1, data2), data3, evmGasLeft) - } - function checkOverflow(data1, data2, evmGasLeft) { if lt(add(data1, data2), data2) { revertWithGas(evmGasLeft) @@ -624,25 +602,6 @@ object "EVMInterpreter" { } } - // Essentially a NOP that will not get optimized away by the compiler - function $llvm_NoInline_llvm$_unoptimized() { - pop(1) - } - - function printHex(value) { - mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebde) - mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) - mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) - $llvm_NoInline_llvm$_unoptimized() - } - - function printString(value) { - mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdf) - mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) - mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) - $llvm_NoInline_llvm$_unoptimized() - } - function isSlotWarm(key) -> isWarm { mstore(0, 0x482D2E7400000000000000000000000000000000000000000000000000000000) mstore(4, key) @@ -688,43 +647,6 @@ object "EVMInterpreter" { originalValue := mload(32) } - function MAX_SYSTEM_CONTRACT_ADDR() -> ret { - ret := 0x000000000000000000000000000000000000ffff - } - - /// @dev Checks whether an address is an EOA (i.e. has not code deployed on it) - /// @param addr The address to check - function isEOA(addr) -> ret { - ret := 0 - if gt(addr, MAX_SYSTEM_CONTRACT_ADDR()) { - ret := iszero(_getRawCodeHash(addr)) - } - } - - function incrementNonce(addr) { - mstore(0, 0x306395C600000000000000000000000000000000000000000000000000000000) - mstore(4, addr) - - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 36, - gas(), - // Only rollup is supported for now - 0, - 0, - 0, - 1 - ) - let to := NONCE_HOLDER_SYSTEM_CONTRACT() - let result := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - - if iszero(result) { - revert(0, 0) - } - } - function getFarCallABI( dataOffset, memoryPage, @@ -1230,38 +1152,6 @@ object "EVMInterpreter" { sp := pushStackItem(sp, success, evmGasLeft) } - function getMessageCallGas ( - _value, - _gas, - _gasLeft, - _memoryCost, - _extraGas - ) -> gasPlusExtra, gasPlusStipend { - let callStipend := 2300 - if iszero(_value) { - callStipend := 0 - } - - switch lt(_gasLeft, add(_extraGas, _memoryCost)) - case 0 - { - let _gasTemp := sub(sub(_gasLeft, _extraGas), _memoryCost) - // From the Tangerine Whistle fork, gas is capped at all but one 64th (remaining_gas / 64) - // of the remaining gas of the current context. If a call tries to send more, the gas is - // changed to match the maximum allowed. - let maxGasToPass := sub(_gasTemp, shr(6, _gasTemp)) // _gas >> 6 == _gas/64 - if gt(_gas, maxGasToPass) { - _gas := maxGasToPass - } - gasPlusExtra := add(_gas, _extraGas) - gasPlusStipend := add(_gas, callStipend) - } - default { - gasPlusExtra := add(_gas, _extraGas) - gasPlusStipend := add(_gas, callStipend) - } - } - function _performStaticCall( _calleeIsEVM, _calleeGas, @@ -2832,11 +2722,10 @@ object "EVMInterpreter" { revertWithGas(evmGasLeft) } - let offset, size, topic1 + let offset, size popStackCheck(sp, evmGasLeft, 3) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - topic1, sp := popStackItemWithoutCheck(sp) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2846,7 +2735,11 @@ object "EVMInterpreter" { dynamicGas := add(dynamicGas, 375) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + { + let topic1 + topic1, sp := popStackItemWithoutCheck(sp) + log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + } ip := add(ip, 1) } case 0xA2 { // OP_LOG2 @@ -2856,7 +2749,7 @@ object "EVMInterpreter" { } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 4) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) @@ -2870,7 +2763,6 @@ object "EVMInterpreter" { { let topic1, topic2 - popStackCheck(sp, evmGasLeft, 2) topic1, sp := popStackItemWithoutCheck(sp) topic2, sp := popStackItemWithoutCheck(sp) log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) @@ -2885,7 +2777,7 @@ object "EVMInterpreter" { } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 5) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) @@ -2899,7 +2791,6 @@ object "EVMInterpreter" { { let topic1, topic2, topic3 - popStackCheck(sp, evmGasLeft, 3) topic1, sp := popStackItemWithoutCheck(sp) topic2, sp := popStackItemWithoutCheck(sp) topic3, sp := popStackItemWithoutCheck(sp) @@ -2915,7 +2806,7 @@ object "EVMInterpreter" { } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 6) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) @@ -2929,7 +2820,6 @@ object "EVMInterpreter" { { let topic1, topic2, topic3, topic4 - popStackCheck(sp, evmGasLeft, 4) topic1, sp := popStackItemWithoutCheck(sp) topic2, sp := popStackItemWithoutCheck(sp) topic3, sp := popStackItemWithoutCheck(sp) @@ -3056,10 +2946,6 @@ object "EVMInterpreter" { } object "EVMInterpreter_deployed" { code { - function SYSTEM_CONTRACTS_OFFSET() -> offset { - offset := 0x8000 - } - function ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008002 } @@ -3072,10 +2958,6 @@ object "EVMInterpreter" { addr := 0x0000000000000000000000000000000000008006 } - function CODE_ADDRESS_CALL_ADDRESS() -> addr { - addr := 0x000000000000000000000000000000000000FFFE - } - function CODE_ORACLE_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008012 } @@ -3084,12 +2966,8 @@ object "EVMInterpreter" { addr := 0x0000000000000000000000000000000000008013 } - function CALLFLAGS_CALL_ADDRESS() -> addr { - addr := 0x000000000000000000000000000000000000FFEF - } - function DEBUG_SLOT_OFFSET() -> offset { - offset := mul(32, 32) + offset := mul(32, 32) // TODO cleanup } function LAST_RETURNDATA_SIZE_OFFSET() -> offset { @@ -3132,6 +3010,25 @@ object "EVMInterpreter" { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } + // Essentially a NOP that will not get optimized away by the compiler + function $llvm_NoInline_llvm$_unoptimized() { + pop(1) + } + + function printHex(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebde) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() + } + + function printString(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdf) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() + } + // It is the responsibility of the caller to ensure that ip >= BYTECODE_OFFSET + 32 function readIP(ip,maxAcceptablePos) -> opcode { if gt(ip, maxAcceptablePos) { @@ -3269,21 +3166,6 @@ object "EVMInterpreter" { hash := mload(0) } - function _getCodeHash(account) -> hash { - // function getCodeHash(uint256 _input) external view override returns (bytes32) - mstore(0, 0xE03FE17700000000000000000000000000000000000000000000000000000000) - mstore(4, account) - - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - hash := mload(0) - } - function getIsStaticFromCallFlags() -> isStatic { isStatic := verbatim_0i_1o("get_global::call_flags") isStatic := iszero(iszero(and(isStatic, 0x04))) @@ -3400,13 +3282,6 @@ object "EVMInterpreter" { } } - function getMin(a, b) -> min { - min := b - if lt(a, b) { - min := a - } - } - function bitLength(n) -> bitLen { for { } gt(n, 0) { } { // while(n > 0) if iszero(n) { @@ -3562,13 +3437,6 @@ object "EVMInterpreter" { } } - function checkMultipleOverflow(data1, data2, data3, evmGasLeft) { - checkOverflow(data1, data2, evmGasLeft) - checkOverflow(data1, data3, evmGasLeft) - checkOverflow(data2, data3, evmGasLeft) - checkOverflow(add(data1, data2), data3, evmGasLeft) - } - function checkOverflow(data1, data2, evmGasLeft) { if lt(add(data1, data2), data2) { revertWithGas(evmGasLeft) @@ -3600,25 +3468,6 @@ object "EVMInterpreter" { } } - // Essentially a NOP that will not get optimized away by the compiler - function $llvm_NoInline_llvm$_unoptimized() { - pop(1) - } - - function printHex(value) { - mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebde) - mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) - mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) - $llvm_NoInline_llvm$_unoptimized() - } - - function printString(value) { - mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdf) - mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) - mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) - $llvm_NoInline_llvm$_unoptimized() - } - function isSlotWarm(key) -> isWarm { mstore(0, 0x482D2E7400000000000000000000000000000000000000000000000000000000) mstore(4, key) @@ -3664,43 +3513,6 @@ object "EVMInterpreter" { originalValue := mload(32) } - function MAX_SYSTEM_CONTRACT_ADDR() -> ret { - ret := 0x000000000000000000000000000000000000ffff - } - - /// @dev Checks whether an address is an EOA (i.e. has not code deployed on it) - /// @param addr The address to check - function isEOA(addr) -> ret { - ret := 0 - if gt(addr, MAX_SYSTEM_CONTRACT_ADDR()) { - ret := iszero(_getRawCodeHash(addr)) - } - } - - function incrementNonce(addr) { - mstore(0, 0x306395C600000000000000000000000000000000000000000000000000000000) - mstore(4, addr) - - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 36, - gas(), - // Only rollup is supported for now - 0, - 0, - 0, - 1 - ) - let to := NONCE_HOLDER_SYSTEM_CONTRACT() - let result := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - - if iszero(result) { - revert(0, 0) - } - } - function getFarCallABI( dataOffset, memoryPage, @@ -4206,38 +4018,6 @@ object "EVMInterpreter" { sp := pushStackItem(sp, success, evmGasLeft) } - function getMessageCallGas ( - _value, - _gas, - _gasLeft, - _memoryCost, - _extraGas - ) -> gasPlusExtra, gasPlusStipend { - let callStipend := 2300 - if iszero(_value) { - callStipend := 0 - } - - switch lt(_gasLeft, add(_extraGas, _memoryCost)) - case 0 - { - let _gasTemp := sub(sub(_gasLeft, _extraGas), _memoryCost) - // From the Tangerine Whistle fork, gas is capped at all but one 64th (remaining_gas / 64) - // of the remaining gas of the current context. If a call tries to send more, the gas is - // changed to match the maximum allowed. - let maxGasToPass := sub(_gasTemp, shr(6, _gasTemp)) // _gas >> 6 == _gas/64 - if gt(_gas, maxGasToPass) { - _gas := maxGasToPass - } - gasPlusExtra := add(_gas, _extraGas) - gasPlusStipend := add(_gas, callStipend) - } - default { - gasPlusExtra := add(_gas, _extraGas) - gasPlusStipend := add(_gas, callStipend) - } - } - function _performStaticCall( _calleeIsEVM, _calleeGas, @@ -5808,11 +5588,10 @@ object "EVMInterpreter" { revertWithGas(evmGasLeft) } - let offset, size, topic1 + let offset, size popStackCheck(sp, evmGasLeft, 3) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - topic1, sp := popStackItemWithoutCheck(sp) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5822,7 +5601,11 @@ object "EVMInterpreter" { dynamicGas := add(dynamicGas, 375) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + { + let topic1 + topic1, sp := popStackItemWithoutCheck(sp) + log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + } ip := add(ip, 1) } case 0xA2 { // OP_LOG2 @@ -5832,7 +5615,7 @@ object "EVMInterpreter" { } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 4) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) @@ -5846,7 +5629,6 @@ object "EVMInterpreter" { { let topic1, topic2 - popStackCheck(sp, evmGasLeft, 2) topic1, sp := popStackItemWithoutCheck(sp) topic2, sp := popStackItemWithoutCheck(sp) log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) @@ -5861,7 +5643,7 @@ object "EVMInterpreter" { } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 5) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) @@ -5875,7 +5657,6 @@ object "EVMInterpreter" { { let topic1, topic2, topic3 - popStackCheck(sp, evmGasLeft, 3) topic1, sp := popStackItemWithoutCheck(sp) topic2, sp := popStackItemWithoutCheck(sp) topic3, sp := popStackItemWithoutCheck(sp) @@ -5891,7 +5672,7 @@ object "EVMInterpreter" { } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 6) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) @@ -5905,7 +5686,6 @@ object "EVMInterpreter" { { let topic1, topic2, topic3, topic4 - popStackCheck(sp, evmGasLeft, 4) topic1, sp := popStackItemWithoutCheck(sp) topic2, sp := popStackItemWithoutCheck(sp) topic3, sp := popStackItemWithoutCheck(sp) diff --git a/system-contracts/contracts/NonceHolder.sol b/system-contracts/contracts/NonceHolder.sol index 232c3e480..cca07b1b4 100644 --- a/system-contracts/contracts/NonceHolder.sol +++ b/system-contracts/contracts/NonceHolder.sol @@ -1,7 +1,5 @@ // SPDX-License-Identifier: MIT -// solhint-disable reason-string, gas-custom-errors - pragma solidity 0.8.24; import {INonceHolder} from "./interfaces/INonceHolder.sol"; diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index 6fe0ae6c1..f42403d3a 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -40,8 +40,6 @@ interface IContractDeployer { event AccountVersionUpdated(address indexed accountAddress, AccountAbstractionVersion aaVersion); - event EVMProxyHashUpdated(bytes32 indexed oldHash, bytes32 indexed newHash); - function getNewAddressCreate2( address _sender, bytes32 _bytecodeHash, diff --git a/system-contracts/contracts/interfaces/IEvmGasManager.sol b/system-contracts/contracts/interfaces/IEvmGasManager.sol index 27c4e59b4..63c42ff2f 100644 --- a/system-contracts/contracts/interfaces/IEvmGasManager.sol +++ b/system-contracts/contracts/interfaces/IEvmGasManager.sol @@ -2,37 +2,12 @@ pragma solidity ^0.8.20; interface IEvmGasManager { - // We need trust to use `storage` pointers - struct WarmAccountInfo { - bool isWarm; - } - - struct SlotInfo { - bool warm; - uint256 originalValue; - } - - // We dont care about the size, since none of it will be stored/pub;ushed anyway. - struct EVMStackFrameInfo { - bool isStatic; - uint256 passGas; - } - function warmAccount(address account) external payable returns (bool wasWarm); function isSlotWarm(uint256 _slot) external view returns (bool); function warmSlot(uint256 _slot, uint256 _currentValue) external payable returns (bool, uint256); - /* - The flow is the following: - When conducting call: - 1. caller calls to an EVM contract pushEVMFrame with the corresponding gas - 2. callee calls consumeEvmFrame to get the gas & make sure that subsequent callee won't be able to read it. - 3. callee sets the return gas - 4. callee calls popEVMFrame to return the gas to the caller & remove the frame - */ - function pushEVMFrame(uint256 _passGas, bool _isStatic) external; function consumeEvmFrame() external returns (uint256 passGas, bool isStatic); diff --git a/system-contracts/contracts/libraries/SystemContractHelper.sol b/system-contracts/contracts/libraries/SystemContractHelper.sol index 43320c0ab..b5934e96a 100644 --- a/system-contracts/contracts/libraries/SystemContractHelper.sol +++ b/system-contracts/contracts/libraries/SystemContractHelper.sol @@ -359,40 +359,4 @@ library SystemContractHelper { revert FailedToChargeGas(); } } - - function mimicCall( - uint32 gasLimit, - address to, - address whoToMimic, - bytes memory data, - bool isConstructorCall, - bool isSystemCall - ) internal returns (bool success) { - address callAddr = MIMIC_CALL_CALL_ADDRESS; - - uint32 dataStart; - assembly { - dataStart := add(data, 0x20) - } - uint32 dataLength = uint32(Utils.safeCastToU32(data.length)); - - // solhint-disable func-named-parameters - uint256 farCallAbi = SystemContractsCaller.getFarCallABI( - 0, - 0, - dataStart, - dataLength, - gasLimit, - // Only rollup is supported for now - 0, - CalldataForwardingMode.UseHeap, - isConstructorCall, - isSystemCall - ); - - // Doing the system call directly - assembly { - success := call(to, callAddr, 0, farCallAbi, whoToMimic, 0, 0) - } - } } diff --git a/system-contracts/contracts/libraries/Utils.sol b/system-contracts/contracts/libraries/Utils.sol index 07e62476a..6ea897f28 100644 --- a/system-contracts/contracts/libraries/Utils.sol +++ b/system-contracts/contracts/libraries/Utils.sol @@ -2,8 +2,6 @@ // We use a floating point pragma here so it can be used within other projects that interact with the ZKsync ecosystem without using our exact pragma version. pragma solidity ^0.8.20; -// solhint-disable gas-custom-errors - import {EfficientCall} from "./EfficientCall.sol"; import {RLPEncoder} from "./RLPEncoder.sol"; import {MalformedBytecode, BytecodeError, Overflow} from "../SystemContractErrors.sol"; diff --git a/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul b/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul index f600df165..4d2f6f3aa 100644 --- a/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul +++ b/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul @@ -1,7 +1,3 @@ -function SYSTEM_CONTRACTS_OFFSET() -> offset { - offset := 0x8000 -} - function ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008002 } @@ -14,10 +10,6 @@ function DEPLOYER_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008006 } -function CODE_ADDRESS_CALL_ADDRESS() -> addr { - addr := 0x000000000000000000000000000000000000FFFE -} - function CODE_ORACLE_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008012 } @@ -26,12 +18,8 @@ function EVM_GAS_MANAGER_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008013 } -function CALLFLAGS_CALL_ADDRESS() -> addr { - addr := 0x000000000000000000000000000000000000FFEF -} - function DEBUG_SLOT_OFFSET() -> offset { - offset := mul(32, 32) + offset := mul(32, 32) // TODO cleanup } function LAST_RETURNDATA_SIZE_OFFSET() -> offset { @@ -74,6 +62,25 @@ function MAX_UINT() -> max_uint { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } +// Essentially a NOP that will not get optimized away by the compiler +function $llvm_NoInline_llvm$_unoptimized() { + pop(1) +} + +function printHex(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebde) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() +} + +function printString(value) { + mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdf) + mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) + mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) + $llvm_NoInline_llvm$_unoptimized() +} + // It is the responsibility of the caller to ensure that ip >= BYTECODE_OFFSET + 32 function readIP(ip,maxAcceptablePos) -> opcode { if gt(ip, maxAcceptablePos) { @@ -211,21 +218,6 @@ function _getRawCodeHash(account) -> hash { hash := mload(0) } -function _getCodeHash(account) -> hash { - // function getCodeHash(uint256 _input) external view override returns (bytes32) - mstore(0, 0xE03FE17700000000000000000000000000000000000000000000000000000000) - mstore(4, account) - - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - hash := mload(0) -} - function getIsStaticFromCallFlags() -> isStatic { isStatic := verbatim_0i_1o("get_global::call_flags") isStatic := iszero(iszero(and(isStatic, 0x04))) @@ -342,13 +334,6 @@ function getMax(a, b) -> max { } } -function getMin(a, b) -> min { - min := b - if lt(a, b) { - min := a - } -} - function bitLength(n) -> bitLen { for { } gt(n, 0) { } { // while(n > 0) if iszero(n) { @@ -504,13 +489,6 @@ function checkMemOverflow(location, evmGasLeft) { } } -function checkMultipleOverflow(data1, data2, data3, evmGasLeft) { - checkOverflow(data1, data2, evmGasLeft) - checkOverflow(data1, data3, evmGasLeft) - checkOverflow(data2, data3, evmGasLeft) - checkOverflow(add(data1, data2), data3, evmGasLeft) -} - function checkOverflow(data1, data2, evmGasLeft) { if lt(add(data1, data2), data2) { revertWithGas(evmGasLeft) @@ -542,25 +520,6 @@ function expandMemory(newSize) -> gasCost { } } -// Essentially a NOP that will not get optimized away by the compiler -function $llvm_NoInline_llvm$_unoptimized() { - pop(1) -} - -function printHex(value) { - mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebde) - mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) - mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) - $llvm_NoInline_llvm$_unoptimized() -} - -function printString(value) { - mstore(add(DEBUG_SLOT_OFFSET(), 0x20), 0x00debdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdebdf) - mstore(add(DEBUG_SLOT_OFFSET(), 0x40), value) - mstore(DEBUG_SLOT_OFFSET(), 0x4A15830341869CAA1E99840C97043A1EA15D2444DA366EFFF5C43B4BEF299681) - $llvm_NoInline_llvm$_unoptimized() -} - function isSlotWarm(key) -> isWarm { mstore(0, 0x482D2E7400000000000000000000000000000000000000000000000000000000) mstore(4, key) @@ -606,43 +565,6 @@ function warmSlot(key,currentValue) -> isWarm, originalValue { originalValue := mload(32) } -function MAX_SYSTEM_CONTRACT_ADDR() -> ret { - ret := 0x000000000000000000000000000000000000ffff -} - -/// @dev Checks whether an address is an EOA (i.e. has not code deployed on it) -/// @param addr The address to check -function isEOA(addr) -> ret { - ret := 0 - if gt(addr, MAX_SYSTEM_CONTRACT_ADDR()) { - ret := iszero(_getRawCodeHash(addr)) - } -} - -function incrementNonce(addr) { - mstore(0, 0x306395C600000000000000000000000000000000000000000000000000000000) - mstore(4, addr) - - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 36, - gas(), - // Only rollup is supported for now - 0, - 0, - 0, - 1 - ) - let to := NONCE_HOLDER_SYSTEM_CONTRACT() - let result := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - - if iszero(result) { - revert(0, 0) - } -} - function getFarCallABI( dataOffset, memoryPage, @@ -1148,38 +1070,6 @@ function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost sp := pushStackItem(sp, success, evmGasLeft) } -function getMessageCallGas ( - _value, - _gas, - _gasLeft, - _memoryCost, - _extraGas -) -> gasPlusExtra, gasPlusStipend { - let callStipend := 2300 - if iszero(_value) { - callStipend := 0 - } - - switch lt(_gasLeft, add(_extraGas, _memoryCost)) - case 0 - { - let _gasTemp := sub(sub(_gasLeft, _extraGas), _memoryCost) - // From the Tangerine Whistle fork, gas is capped at all but one 64th (remaining_gas / 64) - // of the remaining gas of the current context. If a call tries to send more, the gas is - // changed to match the maximum allowed. - let maxGasToPass := sub(_gasTemp, shr(6, _gasTemp)) // _gas >> 6 == _gas/64 - if gt(_gas, maxGasToPass) { - _gas := maxGasToPass - } - gasPlusExtra := add(_gas, _extraGas) - gasPlusStipend := add(_gas, callStipend) - } - default { - gasPlusExtra := add(_gas, _extraGas) - gasPlusStipend := add(_gas, callStipend) - } -} - function _performStaticCall( _calleeIsEVM, _calleeGas, diff --git a/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul b/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul index eb2cac4ec..ae64735c0 100644 --- a/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul +++ b/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul @@ -1272,11 +1272,10 @@ for { } true { } { revertWithGas(evmGasLeft) } - let offset, size, topic1 + let offset, size popStackCheck(sp, evmGasLeft, 3) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) - topic1, sp := popStackItemWithoutCheck(sp) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1286,7 +1285,11 @@ for { } true { } { dynamicGas := add(dynamicGas, 375) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + { + let topic1 + topic1, sp := popStackItemWithoutCheck(sp) + log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + } ip := add(ip, 1) } case 0xA2 { // OP_LOG2 @@ -1296,7 +1299,7 @@ for { } true { } { } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 4) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) @@ -1310,7 +1313,6 @@ for { } true { } { { let topic1, topic2 - popStackCheck(sp, evmGasLeft, 2) topic1, sp := popStackItemWithoutCheck(sp) topic2, sp := popStackItemWithoutCheck(sp) log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) @@ -1325,7 +1327,7 @@ for { } true { } { } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 5) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) @@ -1339,7 +1341,6 @@ for { } true { } { { let topic1, topic2, topic3 - popStackCheck(sp, evmGasLeft, 3) topic1, sp := popStackItemWithoutCheck(sp) topic2, sp := popStackItemWithoutCheck(sp) topic3, sp := popStackItemWithoutCheck(sp) @@ -1355,7 +1356,7 @@ for { } true { } { } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, evmGasLeft, 6) offset, sp := popStackItemWithoutCheck(sp) size, sp := popStackItemWithoutCheck(sp) @@ -1369,7 +1370,6 @@ for { } true { } { { let topic1, topic2, topic3, topic4 - popStackCheck(sp, evmGasLeft, 4) topic1, sp := popStackItemWithoutCheck(sp) topic2, sp := popStackItemWithoutCheck(sp) topic3, sp := popStackItemWithoutCheck(sp) From 6f791dddaf4e1a9d0b7003e5c363ccf24590e9f9 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 24 Sep 2024 01:50:23 +0200 Subject: [PATCH 59/59] Fix EVM branch in getCodeHash (#34) --- system-contracts/contracts/AccountCodeStorage.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/system-contracts/contracts/AccountCodeStorage.sol b/system-contracts/contracts/AccountCodeStorage.sol index 0c7a93c3e..15ccdd9ce 100644 --- a/system-contracts/contracts/AccountCodeStorage.sol +++ b/system-contracts/contracts/AccountCodeStorage.sol @@ -115,9 +115,8 @@ contract AccountCodeStorage is IAccountCodeStorage { // so set `keccak256("")` as a code hash. The EVM has the same behavior. else if (Utils.isContractConstructing(codeHash)) { codeHash = EMPTY_STRING_KECCAK; - } - - if (Utils.isCodeHashEVM(codeHash)) { + } + else if (Utils.isCodeHashEVM(codeHash)) { codeHash = DEPLOYER_SYSTEM_CONTRACT.evmCodeHash(account); }