From 2ff4e59b74deb0fd0e91076d2c763d0e7cd37bcb Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Wed, 7 Aug 2024 17:00:38 -0300 Subject: [PATCH 001/183] 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 002/183] 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 003/183] 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 004/183] 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 005/183] 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 006/183] 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 007/183] 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 008/183] 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 009/183] 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 010/183] 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 011/183] 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 012/183] 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 013/183] 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 014/183] 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 015/183] 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 016/183] 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 017/183] 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 018/183] 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 019/183] 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 020/183] 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 021/183] 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 022/183] 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 023/183] 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 024/183] 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 025/183] 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 026/183] 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 027/183] 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 028/183] 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 029/183] 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 030/183] 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 031/183] 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 032/183] 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 033/183] 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 034/183] 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 035/183] 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 036/183] 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 037/183] 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 038/183] 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 039/183] 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 040/183] 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 041/183] 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 042/183] 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 043/183] 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 044/183] 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 8b5b2964fc78cd94ebea48b172647489f39b1ae3 Mon Sep 17 00:00:00 2001 From: Stanislav Bezkorovainyi Date: Thu, 5 Sep 2024 18:38:38 +0200 Subject: [PATCH 045/183] Implement restriction to allow limiting chain admin in power (#699) Co-authored-by: Vlad Bochok <41153528+vladbochok@users.noreply.github.com> Co-authored-by: Yberjon <106954795+Yberjon@users.noreply.github.com> --- .solhintignore | 1 + .../contracts/common/L1ContractErrors.sol | 22 ++ .../dev-contracts/test/ReenterGovernance.sol | 5 +- .../governance/AccessControlRestriction.sol | 72 ++++++ .../contracts/governance/ChainAdmin.sol | 114 +++++++--- l1-contracts/contracts/governance/Common.sol | 13 ++ .../contracts/governance/Governance.sol | 1 + .../governance/IAccessControlRestriction.sol | 14 ++ .../contracts/governance/IChainAdmin.sol | 39 ++-- .../contracts/governance/IGovernance.sol | 12 +- .../governance/IPermanentRestriction.sol | 17 ++ .../contracts/governance/IRestriction.sol | 15 ++ .../governance/PermanentRestriction.sol | 186 ++++++++++++++++ .../chain-deps/facets/Getters.sol | 5 + .../chain-interfaces/IGetters.sol | 3 + l1-contracts/deploy-scripts/DeployL1.s.sol | 11 +- .../deploy-scripts/RegisterHyperchain.s.sol | 10 +- l1-contracts/deploy-scripts/Utils.sol | 7 +- l1-contracts/src.ts/deploy-process.ts | 3 +- l1-contracts/src.ts/deploy.ts | 14 +- .../foundry/unit/concrete/Utils/Utils.sol | 3 +- .../Governance/AccessControlRestriction.t.sol | 186 ++++++++++++++++ .../Governance/Authorization.t.sol | 0 .../governance/Governance/ChainAdmin.t.sol | 177 +++++++++++++++ .../Governance/Executing.t.sol | 2 +- .../Governance/Fallback.t.sol | 0 .../Governance/OperationStatus.t.sol | 2 +- .../Governance/PermanentRestriction.t.sol | 209 ++++++++++++++++++ .../Governance/Reentrancy.t.sol | 0 .../Governance/SelfUpgrades.t.sol | 2 +- .../Governance/_Governance_Shared.t.sol | 5 +- .../CreateNewChain.t.sol | 4 + .../StateTransitionManager/FreezeChain.t.sol | 4 + .../RevertBatches.t.sol | 4 + .../SetChainCreationParams.t.sol | 4 + .../SetNewVersionUpgrade.t.sol | 4 + .../SetUpgradeDiamondCut.t.sol | 4 + .../SetValidatorTimelock.t.sol | 4 + .../StateTransitionOwnerZero.t.sol | 4 + .../_StateTransitionManager_Shared.t.sol | 13 +- 40 files changed, 1106 insertions(+), 89 deletions(-) create mode 100644 l1-contracts/contracts/governance/AccessControlRestriction.sol create mode 100644 l1-contracts/contracts/governance/Common.sol create mode 100644 l1-contracts/contracts/governance/IAccessControlRestriction.sol create mode 100644 l1-contracts/contracts/governance/IPermanentRestriction.sol create mode 100644 l1-contracts/contracts/governance/IRestriction.sol create mode 100644 l1-contracts/contracts/governance/PermanentRestriction.sol create mode 100644 l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol rename l1-contracts/test/foundry/unit/concrete/{ => governance}/Governance/Authorization.t.sol (100%) create mode 100644 l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol rename l1-contracts/test/foundry/unit/concrete/{ => governance}/Governance/Executing.t.sol (99%) rename l1-contracts/test/foundry/unit/concrete/{ => governance}/Governance/Fallback.t.sol (100%) rename l1-contracts/test/foundry/unit/concrete/{ => governance}/Governance/OperationStatus.t.sol (99%) create mode 100644 l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol rename l1-contracts/test/foundry/unit/concrete/{ => governance}/Governance/Reentrancy.t.sol (100%) rename l1-contracts/test/foundry/unit/concrete/{ => governance}/Governance/SelfUpgrades.t.sol (97%) rename l1-contracts/test/foundry/unit/concrete/{ => governance}/Governance/_Governance_Shared.t.sol (93%) diff --git a/.solhintignore b/.solhintignore index abcb64f98..2371ed166 100644 --- a/.solhintignore +++ b/.solhintignore @@ -8,6 +8,7 @@ l1-contracts/lib l1-contracts/node_modules l1-contracts/contracts/dev-contracts l1-contracts/test +l1-contracts/deploy-scripts # l1-contracts-foundry l1-contracts-foundry/cache diff --git a/l1-contracts/contracts/common/L1ContractErrors.sol b/l1-contracts/contracts/common/L1ContractErrors.sol index 73ff72cc9..bec5a56cd 100644 --- a/l1-contracts/contracts/common/L1ContractErrors.sol +++ b/l1-contracts/contracts/common/L1ContractErrors.sol @@ -1,6 +1,28 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.21; +// 0x5ecf2d7a +error AccessToFallbackDenied(address target, address invoker); +// 0x3995f750 +error AccessToFunctionDenied(address target, bytes4 selector, address invoker); +// 0x6c167909 +error OnlySelfAllowed(); +// 0x52e22c98 +error RestrictionWasNotPresent(address restriction); +// 0xf126e113 +error RestrictionWasAlreadyPresent(address restriction); +// 0x3331e9c0 +error CallNotAllowed(bytes call); +// 0x59e1b0d2 +error ChainZeroAddress(); +// 0xff4bbdf1 +error NotAHyperchain(address chainAddress); +// 0xa3decdf3 +error NotAnAdmin(address expected, address actual); +// 0xf6fd7071 +error RemovingPermanentRestriction(); +// 0xfcb9b2e1 +error UnallowedImplementation(bytes32 implementationHash); // 0x1ff9d522 error AddressAlreadyUsed(address addr); // 0x86bb51b8 diff --git a/l1-contracts/contracts/dev-contracts/test/ReenterGovernance.sol b/l1-contracts/contracts/dev-contracts/test/ReenterGovernance.sol index 0d619c5ba..193f8085f 100644 --- a/l1-contracts/contracts/dev-contracts/test/ReenterGovernance.sol +++ b/l1-contracts/contracts/dev-contracts/test/ReenterGovernance.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.24; import {IGovernance} from "../../governance/IGovernance.sol"; +import {Call} from "../../governance/Common.sol"; contract ReenterGovernance { // add this to be excluded from coverage report @@ -12,7 +13,7 @@ contract ReenterGovernance { // Store call, predecessor and salt separately, // because Operation struct can't be stored on storage. - IGovernance.Call call; + Call call; bytes32 predecessor; bytes32 salt; @@ -45,7 +46,7 @@ contract ReenterGovernance { fallback() external payable { if (!alreadyReentered) { alreadyReentered = true; - IGovernance.Call[] memory calls = new IGovernance.Call[](1); + Call[] memory calls = new Call[](1); calls[0] = call; IGovernance.Operation memory op = IGovernance.Operation({ calls: calls, diff --git a/l1-contracts/contracts/governance/AccessControlRestriction.sol b/l1-contracts/contracts/governance/AccessControlRestriction.sol new file mode 100644 index 000000000..3fc67f875 --- /dev/null +++ b/l1-contracts/contracts/governance/AccessControlRestriction.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {AccessToFallbackDenied, AccessToFunctionDenied} from "../common/L1ContractErrors.sol"; +import {IAccessControlRestriction} from "./IAccessControlRestriction.sol"; +import {AccessControlDefaultAdminRules} from "@openzeppelin/contracts-v4/access/AccessControlDefaultAdminRules.sol"; +import {IRestriction} from "./IRestriction.sol"; +import {Call} from "./Common.sol"; + +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +/// @notice The Restriction that is designed to provide the access control logic for the `ChainAdmin` contract. +/// @dev It inherits from `AccessControlDefaultAdminRules` without overriding `_setRoleAdmin` functionaity. In other +/// words, the `DEFAULT_ADMIN_ROLE` is the only role that can manage roles. This is done for simplicity. +/// @dev An instance of this restriction should be deployed separately for each `ChainAdmin` contract. +/// @dev IMPORTANT: this function does not validate the ability of the invoker to use `msg.value`. Thus, +/// either all callers with access to functions should be trusted to not steal ETH from the `ChainAdmin` account +/// or not ETH should be passively stored in `ChainAdmin` account. +contract AccessControlRestriction is IRestriction, IAccessControlRestriction, AccessControlDefaultAdminRules { + /// @notice Required roles to call a specific functions. + /// @dev Note, that the role 0 means the `DEFAULT_ADMIN_ROLE` from the `AccessControlDefaultAdminRules` contract. + mapping(address target => mapping(bytes4 selector => bytes32 requiredRole)) public requiredRoles; + + /// @notice Required roles to call a fallback function. + mapping(address target => bytes32 requiredRole) public requiredRolesForFallback; + + constructor( + uint48 initialDelay, + address initialDefaultAdmin + ) AccessControlDefaultAdminRules(initialDelay, initialDefaultAdmin) {} + + /// @notice Sets the required role for a specific function call. + /// @param _target The address of the contract. + /// @param _selector The selector of the function. + /// @param _requiredRole The required role. + function setRequiredRoleForCall( + address _target, + bytes4 _selector, + bytes32 _requiredRole + ) external onlyRole(DEFAULT_ADMIN_ROLE) { + requiredRoles[_target][_selector] = _requiredRole; + + emit RoleSet(_target, _selector, _requiredRole); + } + + /// @notice Sets the required role for a fallback function call. + /// @param _target The address of the contract. + /// @param _requiredRole The required role. + function setRequiredRoleForFallback(address _target, bytes32 _requiredRole) external onlyRole(DEFAULT_ADMIN_ROLE) { + requiredRolesForFallback[_target] = _requiredRole; + + emit FallbackRoleSet(_target, _requiredRole); + } + + /// @inheritdoc IRestriction + function validateCall(Call calldata _call, address _invoker) external view { + // Note, that since `DEFAULT_ADMIN_ROLE` is 0 and the default storage value for the + // `requiredRoles` and `requiredRolesForFallback` is 0, the default admin is by default a required + // role for all the functions. + if (_call.data.length < 4) { + if (!hasRole(requiredRolesForFallback[_call.target], _invoker)) { + revert AccessToFallbackDenied(_call.target, _invoker); + } + } else { + bytes4 selector = bytes4(_call.data[:4]); + if (!hasRole(requiredRoles[_call.target][selector], _invoker)) { + revert AccessToFunctionDenied(_call.target, selector, _invoker); + } + } + } +} diff --git a/l1-contracts/contracts/governance/ChainAdmin.sol b/l1-contracts/contracts/governance/ChainAdmin.sol index 4d9ff858f..f6a93146f 100644 --- a/l1-contracts/contracts/governance/ChainAdmin.sol +++ b/l1-contracts/contracts/governance/ChainAdmin.sol @@ -2,48 +2,76 @@ pragma solidity 0.8.24; -import {Ownable2Step} from "@openzeppelin/contracts-v4/access/Ownable2Step.sol"; +// solhint-disable gas-length-in-loops + +import {NoCallsProvided, OnlySelfAllowed, RestrictionWasNotPresent, RestrictionWasAlreadyPresent} from "../common/L1ContractErrors.sol"; import {IChainAdmin} from "./IChainAdmin.sol"; -import {IAdmin} from "../state-transition/chain-interfaces/IAdmin.sol"; -import {NoCallsProvided, Unauthorized, ZeroAddress} from "../common/L1ContractErrors.sol"; +import {IRestriction} from "./IRestriction.sol"; +import {Call} from "./Common.sol"; + +import {EnumerableSet} from "@openzeppelin/contracts-v4/utils/structs/EnumerableSet.sol"; +import {ReentrancyGuard} from "../common/ReentrancyGuard.sol"; /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev /// @notice The contract is designed to hold the `admin` role in ZKSync Chain (State Transition) contracts. /// The owner of the contract can perform any external calls and also save the information needed for -/// the blockchain node to accept the protocol upgrade. Another role - `tokenMultiplierSetter` can be used in the contract -/// to change the base token gas price in the Chain contract. -contract ChainAdmin is IChainAdmin, Ownable2Step { +/// the blockchain node to accept the protocol upgrade. +contract ChainAdmin is IChainAdmin, ReentrancyGuard { + using EnumerableSet for EnumerableSet.AddressSet; + + /// @notice Ensures that only the `ChainAdmin` contract itself can call the function. + /// @dev All functions that require access-control should use `onlySelf` modifier, while the access control logic + /// should be implemented in the restriction contracts. + modifier onlySelf() { + if (msg.sender != address(this)) { + revert OnlySelfAllowed(); + } + _; + } + + constructor(address[] memory _initialRestrictions) reentrancyGuardInitializer { + unchecked { + for (uint256 i = 0; i < _initialRestrictions.length; ++i) { + _addRestriction(_initialRestrictions[i]); + } + } + } + /// @notice Mapping of protocol versions to their expected upgrade timestamps. /// @dev Needed for the offchain node administration to know when to start building batches with the new protocol version. mapping(uint256 protocolVersion => uint256 upgradeTimestamp) public protocolVersionToUpgradeTimestamp; - /// @notice The address which can call `setTokenMultiplier` function to change the base token gas price in the Chain contract. - /// @dev The token base price can be changed quite often, so the private key for this role is supposed to be stored in the node - /// and used by the automated service in a way similar to the sequencer workflow. - address public tokenMultiplierSetter; + /// @notice The set of active restrictions. + EnumerableSet.AddressSet internal activeRestrictions; - constructor(address _initialOwner, address _initialTokenMultiplierSetter) { - if (_initialOwner == address(0)) { - revert ZeroAddress(); - } - _transferOwnership(_initialOwner); - // Can be zero if no one has this permission. - tokenMultiplierSetter = _initialTokenMultiplierSetter; - emit NewTokenMultiplierSetter(address(0), _initialTokenMultiplierSetter); + /// @notice Returns the list of active restrictions. + function getRestrictions() public view returns (address[] memory) { + return activeRestrictions.values(); + } + + /// @inheritdoc IChainAdmin + function isRestrictionActive(address _restriction) external view returns (bool) { + return activeRestrictions.contains(_restriction); } - /// @notice Updates the address responsible for setting token multipliers on the Chain contract . - /// @param _tokenMultiplierSetter The new address to be set as the token multiplier setter. - function setTokenMultiplierSetter(address _tokenMultiplierSetter) external onlyOwner { - emit NewTokenMultiplierSetter(tokenMultiplierSetter, _tokenMultiplierSetter); - tokenMultiplierSetter = _tokenMultiplierSetter; + /// @inheritdoc IChainAdmin + function addRestriction(address _restriction) external onlySelf { + _addRestriction(_restriction); + } + + /// @inheritdoc IChainAdmin + function removeRestriction(address _restriction) external onlySelf { + if (!activeRestrictions.remove(_restriction)) { + revert RestrictionWasNotPresent(_restriction); + } + emit RestrictionRemoved(_restriction); } /// @notice Set the expected upgrade timestamp for a specific protocol version. /// @param _protocolVersion The ZKsync chain protocol version. /// @param _upgradeTimestamp The timestamp at which the chain node should expect the upgrade to happen. - function setUpgradeTimestamp(uint256 _protocolVersion, uint256 _upgradeTimestamp) external onlyOwner { + function setUpgradeTimestamp(uint256 _protocolVersion, uint256 _upgradeTimestamp) external onlySelf { protocolVersionToUpgradeTimestamp[_protocolVersion] = _upgradeTimestamp; emit UpdateUpgradeTimestamp(_protocolVersion, _upgradeTimestamp); } @@ -52,12 +80,16 @@ contract ChainAdmin is IChainAdmin, Ownable2Step { /// @param _calls Array of Call structures defining target, value, and data for each call. /// @param _requireSuccess If true, reverts transaction on any call failure. /// @dev Intended for batch processing of contract interactions, managing gas efficiency and atomicity of operations. - function multicall(Call[] calldata _calls, bool _requireSuccess) external payable onlyOwner { + /// @dev Note, that this function lacks access control. It is expected that the access control is implemented in a separate restriction contract. + /// @dev Even though all the validation from external modules is executed via `staticcall`, the function + /// is marked as `nonReentrant` to prevent reentrancy attacks in case the staticcall restriction is lifted in the future. + function multicall(Call[] calldata _calls, bool _requireSuccess) external payable nonReentrant { if (_calls.length == 0) { revert NoCallsProvided(); } - // solhint-disable-next-line gas-length-in-loops for (uint256 i = 0; i < _calls.length; ++i) { + _validateCall(_calls[i]); + // slither-disable-next-line arbitrary-send-eth (bool success, bytes memory returnData) = _calls[i].target.call{value: _calls[i].value}(_calls[i].data); if (_requireSuccess && !success) { @@ -70,17 +102,27 @@ contract ChainAdmin is IChainAdmin, Ownable2Step { } } - /// @notice Sets the token multiplier in the specified Chain contract. - /// @param _chainContract The chain contract address where the token multiplier will be set. - /// @param _nominator The numerator part of the token multiplier. - /// @param _denominator The denominator part of the token multiplier. - function setTokenMultiplier(IAdmin _chainContract, uint128 _nominator, uint128 _denominator) external { - if (msg.sender != tokenMultiplierSetter) { - revert Unauthorized(msg.sender); + /// @dev Contract might receive/hold ETH as part of the maintenance process. + receive() external payable {} + + /// @notice Function that returns the current admin can perform the call. + /// @dev By default it always returns true, but can be overridden in derived contracts. + function _validateCall(Call calldata _call) internal view { + address[] memory restrictions = getRestrictions(); + + unchecked { + for (uint256 i = 0; i < restrictions.length; ++i) { + IRestriction(restrictions[i]).validateCall(_call, msg.sender); + } } - _chainContract.setTokenMultiplier(_nominator, _denominator); } - /// @dev Contract might receive/hold ETH as part of the maintenance process. - receive() external payable {} + /// @notice Adds a new restriction to the active restrictions set. + /// @param _restriction The address of the restriction contract to be added. + function _addRestriction(address _restriction) internal { + if (!activeRestrictions.add(_restriction)) { + revert RestrictionWasAlreadyPresent(_restriction); + } + emit RestrictionAdded(_restriction); + } } diff --git a/l1-contracts/contracts/governance/Common.sol b/l1-contracts/contracts/governance/Common.sol new file mode 100644 index 000000000..fd73dd793 --- /dev/null +++ b/l1-contracts/contracts/governance/Common.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +/// @dev Represents a call to be made during multicall. +/// @param target The address to which the call will be made. +/// @param value The amount of Ether (in wei) to be sent along with the call. +/// @param data The calldata to be executed on the `target` address. +struct Call { + address target; + uint256 value; + bytes data; +} diff --git a/l1-contracts/contracts/governance/Governance.sol b/l1-contracts/contracts/governance/Governance.sol index 790b79a26..d6e9d9b44 100644 --- a/l1-contracts/contracts/governance/Governance.sol +++ b/l1-contracts/contracts/governance/Governance.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.24; import {Ownable2Step} from "@openzeppelin/contracts-v4/access/Ownable2Step.sol"; import {IGovernance} from "./IGovernance.sol"; +import {Call} from "./Common.sol"; import {ZeroAddress, Unauthorized, OperationMustBeReady, OperationMustBePending, OperationExists, InvalidDelay, PreviousOperationNotExecuted} from "../common/L1ContractErrors.sol"; /// @author Matter Labs diff --git a/l1-contracts/contracts/governance/IAccessControlRestriction.sol b/l1-contracts/contracts/governance/IAccessControlRestriction.sol new file mode 100644 index 000000000..3c9cfb5c5 --- /dev/null +++ b/l1-contracts/contracts/governance/IAccessControlRestriction.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +/// @title AccessControlRestriction contract interface +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +interface IAccessControlRestriction { + /// @notice Emitted when the required role for a specific function is set. + event RoleSet(address indexed target, bytes4 indexed selector, bytes32 requiredRole); + + /// @notice Emitted when the required role for a fallback function is set. + event FallbackRoleSet(address indexed target, bytes32 requiredRole); +} diff --git a/l1-contracts/contracts/governance/IChainAdmin.sol b/l1-contracts/contracts/governance/IChainAdmin.sol index d5d8f117c..1ef3144c2 100644 --- a/l1-contracts/contracts/governance/IChainAdmin.sol +++ b/l1-contracts/contracts/governance/IChainAdmin.sol @@ -2,36 +2,37 @@ pragma solidity 0.8.24; -import {IAdmin} from "../state-transition/chain-interfaces/IAdmin.sol"; +import {Call} from "./Common.sol"; /// @title ChainAdmin contract interface /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev interface IChainAdmin { - /// @dev Represents a call to be made during multicall. - /// @param target The address to which the call will be made. - /// @param value The amount of Ether (in wei) to be sent along with the call. - /// @param data The calldata to be executed on the `target` address. - struct Call { - address target; - uint256 value; - bytes data; - } - /// @notice Emitted when the expected upgrade timestamp for a specific protocol version is set. - event UpdateUpgradeTimestamp(uint256 indexed _protocolVersion, uint256 _upgradeTimestamp); + event UpdateUpgradeTimestamp(uint256 indexed protocolVersion, uint256 upgradeTimestamp); /// @notice Emitted when the call is executed from the contract. - event CallExecuted(Call _call, bool _success, bytes _returnData); + event CallExecuted(Call call, bool success, bytes returnData); + + /// @notice Emitted when a new restriction is added. + event RestrictionAdded(address indexed restriction); - /// @notice Emitted when the new token multiplier address is set. - event NewTokenMultiplierSetter(address _oldTokenMultiplierSetter, address _newTokenMultiplierSetter); + /// @notice Emitted when a restriction is removed. + event RestrictionRemoved(address indexed restriction); - function setTokenMultiplierSetter(address _tokenMultiplierSetter) external; + /// @notice Returns the list of active restrictions. + function getRestrictions() external view returns (address[] memory); - function setUpgradeTimestamp(uint256 _protocolVersion, uint256 _upgradeTimestamp) external; + /// @notice Checks if the restriction is active. + /// @param _restriction The address of the restriction contract. + function isRestrictionActive(address _restriction) external view returns (bool); - function multicall(Call[] calldata _calls, bool _requireSuccess) external payable; + /// @notice Adds a new restriction to the active restrictions set. + /// @param _restriction The address of the restriction contract. + function addRestriction(address _restriction) external; - function setTokenMultiplier(IAdmin _chainContract, uint128 _nominator, uint128 _denominator) external; + /// @notice Removes a restriction from the active restrictions set. + /// @param _restriction The address of the restriction contract. + /// @dev Sometimes restrictions might need to enforce their permanence (e.g. if a chain should be a rollup forever). + function removeRestriction(address _restriction) external; } diff --git a/l1-contracts/contracts/governance/IGovernance.sol b/l1-contracts/contracts/governance/IGovernance.sol index 2b03ed4c9..0cb478573 100644 --- a/l1-contracts/contracts/governance/IGovernance.sol +++ b/l1-contracts/contracts/governance/IGovernance.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.21; +import {Call} from "./Common.sol"; + /// @title Governance contract interface /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev @@ -18,16 +20,6 @@ interface IGovernance { Done } - /// @dev Represents a call to be made during an operation. - /// @param target The address to which the call will be made. - /// @param value The amount of Ether (in wei) to be sent along with the call. - /// @param data The calldata to be executed on the `target` address. - struct Call { - address target; - uint256 value; - bytes data; - } - /// @dev Defines the structure of an operation that Governance executes. /// @param calls An array of `Call` structs, each representing a call to be made during the operation. /// @param predecessor The hash of the predecessor operation, that should be executed before this operation. diff --git a/l1-contracts/contracts/governance/IPermanentRestriction.sol b/l1-contracts/contracts/governance/IPermanentRestriction.sol new file mode 100644 index 000000000..548866b9f --- /dev/null +++ b/l1-contracts/contracts/governance/IPermanentRestriction.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +/// @notice The interface for the permanent restriction contract. +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +interface IPermanentRestriction { + /// @notice Emitted when the implementation is allowed or disallowed. + event AdminImplementationAllowed(bytes32 indexed implementationHash, bool isAllowed); + + /// @notice Emitted when a certain calldata is allowed or disallowed. + event AllowedDataChanged(bytes data, bool isAllowed); + + /// @notice Emitted when the selector is labeled as validated or not. + event SelectorValidationChanged(bytes4 indexed selector, bool isValidated); +} diff --git a/l1-contracts/contracts/governance/IRestriction.sol b/l1-contracts/contracts/governance/IRestriction.sol new file mode 100644 index 000000000..b2cc79428 --- /dev/null +++ b/l1-contracts/contracts/governance/IRestriction.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {Call} from "./Common.sol"; + +/// @title Restriction contract interface +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +interface IRestriction { + /// @notice Ensures that the invoker has the required role to call the function. + /// @param _call The call data. + /// @param _invoker The address of the invoker. + function validateCall(Call calldata _call, address _invoker) external view; +} diff --git a/l1-contracts/contracts/governance/PermanentRestriction.sol b/l1-contracts/contracts/governance/PermanentRestriction.sol new file mode 100644 index 000000000..acf75a67f --- /dev/null +++ b/l1-contracts/contracts/governance/PermanentRestriction.sol @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {CallNotAllowed, ChainZeroAddress, NotAHyperchain, NotAnAdmin, RemovingPermanentRestriction, ZeroAddress, UnallowedImplementation} from "../common/L1ContractErrors.sol"; + +import {Ownable2Step} from "@openzeppelin/contracts-v4/access/Ownable2Step.sol"; + +import {Call} from "./Common.sol"; +import {IRestriction} from "./IRestriction.sol"; +import {IChainAdmin} from "./IChainAdmin.sol"; +import {IBridgehub} from "../bridgehub/IBridgehub.sol"; +import {IZkSyncHyperchain} from "../state-transition/chain-interfaces/IZkSyncHyperchain.sol"; +import {IAdmin} from "../state-transition/chain-interfaces/IAdmin.sol"; + +import {IPermanentRestriction} from "./IPermanentRestriction.sol"; + +/// @title PermanentRestriction contract +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +/// @notice This contract should be used by chains that wish to guarantee that certain security +/// properties are preserved forever. +/// @dev To be deployed as a transparent upgradable proxy, owned by a trusted decentralized governance. +/// @dev Once of the instances of such contract is to ensure that a ZkSyncHyperchain is a rollup forever. +contract PermanentRestriction is IRestriction, IPermanentRestriction, Ownable2Step { + /// @notice The address of the Bridgehub contract. + IBridgehub public immutable BRIDGE_HUB; + + /// @notice The mapping of the allowed admin implementations. + mapping(bytes32 implementationCodeHash => bool isAllowed) public allowedAdminImplementations; + + /// @notice The mapping of the allowed calls. + mapping(bytes allowedCalldata => bool isAllowed) public allowedCalls; + + /// @notice The mapping of the validated selectors. + mapping(bytes4 selector => bool isValidated) public validatedSelectors; + + constructor(address _initialOwner, IBridgehub _bridgehub) { + BRIDGE_HUB = _bridgehub; + + // solhint-disable-next-line gas-custom-errors, reason-string + if (_initialOwner == address(0)) { + revert ZeroAddress(); + } + _transferOwnership(_initialOwner); + } + + /// @notice Allows a certain `ChainAdmin` implementation to be used as an admin. + /// @param _implementationHash The hash of the implementation code. + /// @param _isAllowed The flag that indicates if the implementation is allowed. + function allowAdminImplementation(bytes32 _implementationHash, bool _isAllowed) external onlyOwner { + allowedAdminImplementations[_implementationHash] = _isAllowed; + + emit AdminImplementationAllowed(_implementationHash, _isAllowed); + } + + /// @notice Allows a certain calldata for a selector to be used. + /// @param _data The calldata for the function. + /// @param _isAllowed The flag that indicates if the calldata is allowed. + function setAllowedData(bytes calldata _data, bool _isAllowed) external onlyOwner { + allowedCalls[_data] = _isAllowed; + + emit AllowedDataChanged(_data, _isAllowed); + } + + /// @notice Allows a certain selector to be validated. + /// @param _selector The selector of the function. + /// @param _isValidated The flag that indicates if the selector is validated. + function setSelectorIsValidated(bytes4 _selector, bool _isValidated) external onlyOwner { + validatedSelectors[_selector] = _isValidated; + + emit SelectorValidationChanged(_selector, _isValidated); + } + + /// @inheritdoc IRestriction + function validateCall( + Call calldata _call, + address // _invoker + ) external view override { + _validateAsChainAdmin(_call); + _validateRemoveRestriction(_call); + } + + /// @notice Validates the call as the chain admin + /// @param _call The call data. + function _validateAsChainAdmin(Call calldata _call) internal view { + if (!_isAdminOfAChain(_call.target)) { + // We only validate calls related to being an admin of a chain + return; + } + + // All calls with the length of the data below 4 will get into `receive`/`fallback` functions, + // we consider it to always be allowed. + if (_call.data.length < 4) { + return; + } + + bytes4 selector = bytes4(_call.data[:4]); + + if (selector == IAdmin.setPendingAdmin.selector) { + _validateNewAdmin(_call); + return; + } + + if (!validatedSelectors[selector]) { + // The selector is not validated, any data is allowed. + return; + } + + if (!allowedCalls[_call.data]) { + revert CallNotAllowed(_call.data); + } + } + + /// @notice Validates the correctness of the new admin. + /// @param _call The call data. + /// @dev Ensures that the admin has a whitelisted implementation and does not remove this restriction. + function _validateNewAdmin(Call calldata _call) internal view { + address newChainAdmin = abi.decode(_call.data[4:], (address)); + + bytes32 implementationCodeHash = newChainAdmin.codehash; + + if (!allowedAdminImplementations[implementationCodeHash]) { + revert UnallowedImplementation(implementationCodeHash); + } + + // Since the implementation is known to be correct (from the checks above), we + // can safely trust the returned value from the call below + if (!IChainAdmin(newChainAdmin).isRestrictionActive(address(this))) { + revert RemovingPermanentRestriction(); + } + } + + /// @notice Validates the removal of the restriction. + /// @param _call The call data. + /// @dev Ensures that this restriction is not removed. + function _validateRemoveRestriction(Call calldata _call) internal view { + if (_call.target != msg.sender) { + return; + } + + if (bytes4(_call.data[:4]) != IChainAdmin.removeRestriction.selector) { + return; + } + + address removedRestriction = abi.decode(_call.data[4:], (address)); + + if (removedRestriction == address(this)) { + revert RemovingPermanentRestriction(); + } + } + + /// @notice Checks if the `msg.sender` is an admin of a certain ZkSyncHyperchain. + /// @param _chain The address of the chain. + function _isAdminOfAChain(address _chain) internal view returns (bool) { + (bool success, ) = address(this).staticcall(abi.encodeCall(this.tryCompareAdminOfAChain, (_chain, msg.sender))); + return success; + } + + /// @notice Tries to compare the admin of a chain with the potential admin. + /// @param _chain The address of the chain. + /// @param _potentialAdmin The address of the potential admin. + /// @dev This function reverts if the `_chain` is not a ZkSyncHyperchain or the `_potentialAdmin` is not the + /// admin of the chain. + function tryCompareAdminOfAChain(address _chain, address _potentialAdmin) external view { + if (_chain == address(0)) { + revert ChainZeroAddress(); + } + + // Unfortunately there is no easy way to double check that indeed the `_chain` is a ZkSyncHyperchain. + // So we do the following: + // - Query it for `chainId`. If it reverts, it is not a ZkSyncHyperchain. + // - Query the Bridgehub for the Hyperchain with the given `chainId`. + // - We compare the corresponding addresses + uint256 chainId = IZkSyncHyperchain(_chain).getChainId(); + if (BRIDGE_HUB.getHyperchain(chainId) != _chain) { + revert NotAHyperchain(_chain); + } + + // Now, the chain is known to be a hyperchain, so it should implement the corresponding interface + address admin = IZkSyncHyperchain(_chain).getAdmin(); + if (admin != _potentialAdmin) { + revert NotAnAdmin(admin, _potentialAdmin); + } + } +} 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 9cb2a2da8..604eeef2e 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol @@ -52,6 +52,11 @@ contract GettersFacet is ZkSyncHyperchainBase, IGetters, ILegacyGetters { return s.bridgehub; } + /// @inheritdoc IGetters + function getChainId() external view returns (uint256) { + return s.chainId; + } + /// @inheritdoc IGetters function getStateTransitionManager() external view returns (address) { return s.stateTransitionManager; diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol index 4d06f9e8e..5da8cc748 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol @@ -33,6 +33,9 @@ interface IGetters is IZkSyncHyperchainBase { /// @return The address of the base token function getBaseToken() external view returns (address); + /// @return The chain id of the ZK Chain. + function getChainId() external view returns (uint256); + /// @return The address of the base token bridge function getBaseTokenBridge() external view returns (address); diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 098aee5bc..cef851957 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -302,10 +302,17 @@ contract DeployL1Script is Script { } function deployChainAdmin() internal { - bytes memory bytecode = abi.encodePacked( + bytes memory accessControlRestrictionBytecode = abi.encodePacked( type(ChainAdmin).creationCode, - abi.encode(config.ownerAddress, address(0)) + abi.encode(uint256(0), config.ownerAddress) ); + + address accessControlRestriction = deployViaCreate2(accessControlRestrictionBytecode); + console.log("Access control restriction deployed at:", accessControlRestriction); + address[] memory restrictions = new address[](1); + restrictions[0] = accessControlRestriction; + + bytes memory bytecode = abi.encodePacked(type(ChainAdmin).creationCode, abi.encode(restrictions)); address contractAddress = deployViaCreate2(bytecode); console.log("ChainAdmin deployed at:", contractAddress); addresses.chainAdmin = contractAddress; diff --git a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol index e0039b969..94acb2f02 100644 --- a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol +++ b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol @@ -13,6 +13,7 @@ import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZk import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol"; import {Governance} from "contracts/governance/Governance.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; +import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; import {Utils} from "./Utils.sol"; import {PubdataPricingMode} from "contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol"; @@ -151,8 +152,13 @@ contract RegisterHyperchainScript is Script { function deployChainAdmin() internal { vm.broadcast(); - ChainAdmin chainAdmin = new ChainAdmin(config.ownerAddress, address(0)); - console.log("ChainAdmin deployed at:", address(chainAdmin)); + AccessControlRestriction restriction = new AccessControlRestriction(0, config.ownerAddress); + + address[] memory restrictions = new address[](1); + restrictions[0] = address(restriction); + + vm.broadcast(); + ChainAdmin chainAdmin = new ChainAdmin(restrictions); config.chainAdmin = address(chainAdmin); } diff --git a/l1-contracts/deploy-scripts/Utils.sol b/l1-contracts/deploy-scripts/Utils.sol index 17449da7e..440eadcac 100644 --- a/l1-contracts/deploy-scripts/Utils.sol +++ b/l1-contracts/deploy-scripts/Utils.sol @@ -8,7 +8,8 @@ import {Vm} from "forge-std/Vm.sol"; import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {L2TransactionRequestDirect} from "contracts/bridgehub/IBridgehub.sol"; import {IGovernance} from "contracts/governance/IGovernance.sol"; -import {IERC20} from "@openzeppelin/contracts-v4/token/ERC20/IERC20.sol"; +import {Call} from "contracts/governance/Common.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA} from "contracts/common/Config.sol"; import {L2_DEPLOYER_SYSTEM_CONTRACT_ADDR} from "contracts/common/L2ContractAddresses.sol"; import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; @@ -316,8 +317,8 @@ library Utils { ) internal { IGovernance governance = IGovernance(_governor); - IGovernance.Call[] memory calls = new IGovernance.Call[](1); - calls[0] = IGovernance.Call({target: _target, value: _value, data: _data}); + Call[] memory calls = new Call[](1); + calls[0] = Call({target: _target, value: _value, data: _data}); IGovernance.Operation memory operation = IGovernance.Operation({ calls: calls, diff --git a/l1-contracts/src.ts/deploy-process.ts b/l1-contracts/src.ts/deploy-process.ts index d30762a15..285dd9e0e 100644 --- a/l1-contracts/src.ts/deploy-process.ts +++ b/l1-contracts/src.ts/deploy-process.ts @@ -58,9 +58,8 @@ export async function initialBridgehubDeployment( nonce++; await deployer.deployGovernance(create2Salt, { gasPrice, nonce }); - nonce++; - await deployer.deployChainAdmin(create2Salt, { gasPrice, nonce }); + await deployer.deployChainAdmin(create2Salt, { gasPrice }); await deployer.deployTransparentProxyAdmin(create2Salt, { gasPrice }); await deployer.deployBridgehubContract(create2Salt, gasPrice); await deployer.deployBlobVersionedHashRetriever(create2Salt, { gasPrice }); diff --git a/l1-contracts/src.ts/deploy.ts b/l1-contracts/src.ts/deploy.ts index 3ee3bb07b..d131d269c 100644 --- a/l1-contracts/src.ts/deploy.ts +++ b/l1-contracts/src.ts/deploy.ts @@ -212,9 +212,21 @@ export class Deployer { public async deployChainAdmin(create2Salt: string, ethTxOptions: ethers.providers.TransactionRequest) { ethTxOptions.gasLimit ??= 10_000_000; + // Firstly, we deploy the access control restriction for the chain admin + const accessControlRestriction = await this.deployViaCreate2( + "AccessControlRestriction", + [0, this.ownerAddress], + create2Salt, + ethTxOptions + ); + if (this.verbose) { + console.log(`CONTRACTS_ACCESS_CONTROL_RESTRICTION_ADDR=${accessControlRestriction}`); + } + + // Then we deploy the ChainAdmin contract itself const contractAddress = await this.deployViaCreate2( "ChainAdmin", - [this.ownerAddress, ethers.constants.AddressZero], + [[accessControlRestriction]], create2Salt, ethTxOptions ); diff --git a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol index 1260334fd..3b46d212a 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; @@ -240,6 +240,7 @@ library Utils { selectors[26] = GettersFacet.getTotalBatchesVerified.selector; selectors[27] = GettersFacet.getTotalBatchesExecuted.selector; selectors[28] = GettersFacet.getL2SystemContractsUpgradeTxHash.selector; + selectors[29] = GettersFacet.getChainId.selector; return selectors; } diff --git a/l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol new file mode 100644 index 000000000..e5b45975f --- /dev/null +++ b/l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; + +import "openzeppelin-contracts/contracts/utils/Strings.sol"; +import "forge-std/console.sol"; +import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; +import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; +import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; +import {IAccessControlRestriction} from "contracts/governance/IAccessControlRestriction.sol"; +import {Utils} from "test/foundry/unit/concrete/Utils/Utils.sol"; +import {NoCallsProvided, AccessToFallbackDenied, AccessToFunctionDenied} from "contracts/common/L1ContractErrors.sol"; +import {Call} from "contracts/governance/Common.sol"; + +contract AccessRestrictionTest is Test { + AccessControlRestriction internal restriction; + ChainAdmin internal chainAdmin; + address owner; + address randomCaller; + bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + + function getChainAdminSelectors() public pure returns (bytes4[] memory) { + bytes4[] memory selectors = new bytes4[](12); + selectors[0] = IChainAdmin.getRestrictions.selector; + selectors[1] = IChainAdmin.isRestrictionActive.selector; + selectors[2] = IChainAdmin.addRestriction.selector; + selectors[3] = IChainAdmin.removeRestriction.selector; + + return selectors; + } + + function setUp() public { + owner = makeAddr("random address"); + randomCaller = makeAddr("random caller"); + + restriction = new AccessControlRestriction(0, owner); + address[] memory restrictions = new address[](1); + restrictions[0] = address(restriction); + + chainAdmin = new ChainAdmin(restrictions); + } + + function test_adminAsAddressZero() public { + vm.expectRevert("AccessControl: 0 default admin"); + new AccessControlRestriction(0, address(0)); + } + + function test_setRequiredRoleForCallByNotDefaultAdmin(bytes32 role) public { + vm.assume(role != DEFAULT_ADMIN_ROLE); + + bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); + string memory revertMsg = string( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(uint160(randomCaller), 20), + " is missing role ", + Strings.toHexString(uint256(DEFAULT_ADMIN_ROLE), 32) + ) + ); + + vm.expectRevert(bytes(revertMsg)); + vm.prank(randomCaller); + restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); + } + + function test_setRequiredRoleForCallAccessToFunctionDenied(bytes32 role) public { + vm.assume(role != DEFAULT_ADMIN_ROLE); + + bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); + + vm.startPrank(owner); + restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); + vm.stopPrank(); + + Call memory call = Call({ + target: address(chainAdmin), + value: 0, + data: abi.encodeCall(IChainAdmin.getRestrictions, ()) + }); + + vm.expectRevert( + abi.encodeWithSelector( + AccessToFunctionDenied.selector, + address(chainAdmin), + chainAdminSelectors[0], + randomCaller + ) + ); + restriction.validateCall(call, randomCaller); + } + + function test_setRequiredRoleForCall(bytes32 role) public { + vm.assume(role != DEFAULT_ADMIN_ROLE); + + bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); + + vm.expectEmit(true, true, false, true); + emit IAccessControlRestriction.RoleSet(address(chainAdmin), chainAdminSelectors[0], role); + + vm.startPrank(owner); + restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); + restriction.grantRole(role, randomCaller); + vm.stopPrank(); + + Call memory call = Call({ + target: address(chainAdmin), + value: 0, + data: abi.encodeCall(IChainAdmin.getRestrictions, ()) + }); + restriction.validateCall(call, randomCaller); + } + + function test_setRequiredRoleForFallbackByNotDefaultAdmin(bytes32 role) public { + vm.assume(role != DEFAULT_ADMIN_ROLE); + + string memory revertMsg = string( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(uint160(randomCaller), 20), + " is missing role ", + Strings.toHexString(uint256(DEFAULT_ADMIN_ROLE), 32) + ) + ); + + vm.expectRevert(bytes(revertMsg)); + vm.prank(randomCaller); + restriction.setRequiredRoleForFallback(address(chainAdmin), role); + } + + function test_setRequiredRoleForFallbackAccessToFallbackDenied(bytes32 role) public { + vm.assume(role != DEFAULT_ADMIN_ROLE); + + vm.startPrank(owner); + restriction.setRequiredRoleForFallback(address(chainAdmin), role); + vm.stopPrank(); + + Call memory call = Call({target: address(chainAdmin), value: 0, data: ""}); + + vm.expectRevert(abi.encodeWithSelector(AccessToFallbackDenied.selector, address(chainAdmin), randomCaller)); + restriction.validateCall(call, randomCaller); + } + + function test_setRequiredRoleForFallback(bytes32 role) public { + vm.assume(role != DEFAULT_ADMIN_ROLE); + + vm.expectEmit(true, false, false, true); + emit IAccessControlRestriction.FallbackRoleSet(address(chainAdmin), role); + + vm.startPrank(owner); + restriction.setRequiredRoleForFallback(address(chainAdmin), role); + restriction.grantRole(role, randomCaller); + vm.stopPrank(); + + Call memory call = Call({target: address(chainAdmin), value: 0, data: ""}); + restriction.validateCall(call, randomCaller); + } + + function test_validateCallFunction(bytes32 role) public { + vm.assume(role != DEFAULT_ADMIN_ROLE); + + bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); + vm.startPrank(owner); + restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); + restriction.grantRole(role, randomCaller); + vm.stopPrank(); + + Call memory call = Call({ + target: address(chainAdmin), + value: 0, + data: abi.encodeCall(IChainAdmin.getRestrictions, ()) + }); + restriction.validateCall(call, randomCaller); + } + + function test_validateCallFallback(bytes32 role) public { + vm.assume(role != DEFAULT_ADMIN_ROLE); + vm.startPrank(owner); + restriction.setRequiredRoleForFallback(address(chainAdmin), role); + restriction.grantRole(role, randomCaller); + vm.stopPrank(); + + Call memory call = Call({target: address(chainAdmin), value: 0, data: ""}); + restriction.validateCall(call, randomCaller); + } +} diff --git a/l1-contracts/test/foundry/unit/concrete/Governance/Authorization.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/Authorization.t.sol similarity index 100% rename from l1-contracts/test/foundry/unit/concrete/Governance/Authorization.t.sol rename to l1-contracts/test/foundry/unit/concrete/governance/Governance/Authorization.t.sol diff --git a/l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol new file mode 100644 index 000000000..01a3c7dfd --- /dev/null +++ b/l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; + +import "openzeppelin-contracts/contracts/utils/Strings.sol"; +import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; +import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; +import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; +import {GettersFacet} from "contracts/state-transition/chain-deps/facets/Getters.sol"; +import {Call} from "contracts/governance/Common.sol"; +import {NoCallsProvided, RestrictionWasAlreadyPresent, RestrictionWasNotPresent, AccessToFallbackDenied, AccessToFunctionDenied} from "contracts/common/L1ContractErrors.sol"; +import {Utils} from "test/foundry/unit/concrete/Utils/Utils.sol"; + +contract ChainAdminTest is Test { + ChainAdmin internal chainAdmin; + AccessControlRestriction internal restriction; + GettersFacet internal gettersFacet; + + address internal owner; + uint32 internal major; + uint32 internal minor; + uint32 internal patch; + bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + + function setUp() public { + owner = makeAddr("random address"); + + restriction = new AccessControlRestriction(0, owner); + address[] memory restrictions = new address[](1); + restrictions[0] = address(restriction); + + chainAdmin = new ChainAdmin(restrictions); + + gettersFacet = new GettersFacet(); + } + + function test_getRestrictions() public { + address[] memory restrictions = chainAdmin.getRestrictions(); + assertEq(restrictions[0], address(restriction)); + } + + function test_isRestrictionActive() public { + bool isActive = chainAdmin.isRestrictionActive(address(restriction)); + assertEq(isActive, true); + } + + function test_addRestriction() public { + address[] memory restrictions = chainAdmin.getRestrictions(); + + vm.expectEmit(true, false, false, true); + emit IChainAdmin.RestrictionAdded(owner); + + vm.prank(address(chainAdmin)); + chainAdmin.addRestriction(owner); + } + + function test_addRestrictionRevert() public { + vm.startPrank(address(chainAdmin)); + chainAdmin.addRestriction(owner); + + vm.expectRevert(abi.encodeWithSelector(RestrictionWasAlreadyPresent.selector, owner)); + chainAdmin.addRestriction(owner); + vm.stopPrank(); + } + + function test_removeRestriction() public { + address[] memory restrictions = chainAdmin.getRestrictions(); + + vm.startPrank(address(chainAdmin)); + chainAdmin.addRestriction(owner); + + vm.expectEmit(true, false, false, true); + emit IChainAdmin.RestrictionRemoved(owner); + + chainAdmin.removeRestriction(owner); + vm.stopPrank(); + } + + function test_removeRestrictionRevert() public { + address[] memory restrictions = chainAdmin.getRestrictions(); + + vm.startPrank(address(chainAdmin)); + chainAdmin.addRestriction(owner); + chainAdmin.removeRestriction(owner); + + vm.expectRevert(abi.encodeWithSelector(RestrictionWasNotPresent.selector, owner)); + chainAdmin.removeRestriction(owner); + vm.stopPrank(); + } + + function test_setUpgradeTimestamp(uint256 semverMinorVersionMultiplier, uint256 timestamp) public { + (major, minor, patch) = gettersFacet.getSemverProtocolVersion(); + uint256 protocolVersion = packSemver(major, minor, patch + 1, semverMinorVersionMultiplier); + + vm.expectEmit(true, false, false, true); + emit IChainAdmin.UpdateUpgradeTimestamp(protocolVersion, timestamp); + + vm.prank(address(chainAdmin)); + chainAdmin.setUpgradeTimestamp(protocolVersion, timestamp); + } + + function test_multicallRevertNoCalls() public { + Call[] memory calls = new Call[](0); + + vm.expectRevert(NoCallsProvided.selector); + chainAdmin.multicall(calls, false); + } + + function test_multicallRevertFailedCall() public { + Call[] memory calls = new Call[](1); + calls[0] = Call({target: address(chainAdmin), value: 0, data: abi.encodeCall(gettersFacet.getAdmin, ())}); + + vm.expectRevert(); + vm.prank(owner); + chainAdmin.multicall(calls, true); + } + + function test_validateCallAccessToFunctionDenied(bytes32 role) public { + vm.assume(role != DEFAULT_ADMIN_ROLE); + + Call[] memory calls = new Call[](2); + calls[0] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getAdmin, ())}); + calls[1] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getVerifier, ())}); + + vm.prank(owner); + restriction.setRequiredRoleForCall(address(gettersFacet), gettersFacet.getAdmin.selector, role); + + vm.expectRevert( + abi.encodeWithSelector( + AccessToFunctionDenied.selector, + address(gettersFacet), + gettersFacet.getAdmin.selector, + owner + ) + ); + vm.prank(owner); + chainAdmin.multicall(calls, true); + } + + function test_validateCallAccessToFallbackDenied(bytes32 role) public { + vm.assume(role != DEFAULT_ADMIN_ROLE); + + Call[] memory calls = new Call[](2); + calls[0] = Call({target: address(gettersFacet), value: 0, data: ""}); + calls[1] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getVerifier, ())}); + + vm.prank(owner); + restriction.setRequiredRoleForFallback(address(gettersFacet), role); + + vm.expectRevert(abi.encodeWithSelector(AccessToFallbackDenied.selector, address(gettersFacet), owner)); + vm.prank(owner); + chainAdmin.multicall(calls, true); + } + + function test_multicall() public { + Call[] memory calls = new Call[](2); + calls[0] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getAdmin, ())}); + calls[1] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getVerifier, ())}); + + vm.prank(owner); + chainAdmin.multicall(calls, true); + } + + function packSemver( + uint32 major, + uint32 minor, + uint32 patch, + uint256 semverMinorVersionMultiplier + ) public returns (uint256) { + if (major != 0) { + revert("Major version must be 0"); + } + + return minor * semverMinorVersionMultiplier + patch; + } +} diff --git a/l1-contracts/test/foundry/unit/concrete/Governance/Executing.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/Executing.t.sol similarity index 99% rename from l1-contracts/test/foundry/unit/concrete/Governance/Executing.t.sol rename to l1-contracts/test/foundry/unit/concrete/governance/Governance/Executing.t.sol index 9a1e5eeb2..09d6c0267 100644 --- a/l1-contracts/test/foundry/unit/concrete/Governance/Executing.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/governance/Governance/Executing.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import {StdStorage, stdStorage} from "forge-std/Test.sol"; -import {Utils} from "../Utils/Utils.sol"; +import {Utils} from "../../Utils/Utils.sol"; import {GovernanceTest} from "./_Governance_Shared.t.sol"; diff --git a/l1-contracts/test/foundry/unit/concrete/Governance/Fallback.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/Fallback.t.sol similarity index 100% rename from l1-contracts/test/foundry/unit/concrete/Governance/Fallback.t.sol rename to l1-contracts/test/foundry/unit/concrete/governance/Governance/Fallback.t.sol diff --git a/l1-contracts/test/foundry/unit/concrete/Governance/OperationStatus.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/OperationStatus.t.sol similarity index 99% rename from l1-contracts/test/foundry/unit/concrete/Governance/OperationStatus.t.sol rename to l1-contracts/test/foundry/unit/concrete/governance/Governance/OperationStatus.t.sol index 131bb6465..9b4ee36e9 100644 --- a/l1-contracts/test/foundry/unit/concrete/Governance/OperationStatus.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/governance/Governance/OperationStatus.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {Utils} from "../Utils/Utils.sol"; +import {Utils} from "../../Utils/Utils.sol"; import {GovernanceTest} from "./_Governance_Shared.t.sol"; diff --git a/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol new file mode 100644 index 000000000..0e9dc0bce --- /dev/null +++ b/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol @@ -0,0 +1,209 @@ +pragma solidity 0.8.24; + +import "openzeppelin-contracts/contracts/utils/Strings.sol"; +import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; +import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; +import {StateTransitionManager} from "contracts/state-transition/StateTransitionManager.sol"; +import {DiamondInit} from "contracts/state-transition/chain-deps/DiamondInit.sol"; +import {PermanentRestriction} from "contracts/governance/PermanentRestriction.sol"; +import {IPermanentRestriction} from "contracts/governance/IPermanentRestriction.sol"; +import {ZeroAddress, ChainZeroAddress, NotAnAdmin, UnallowedImplementation, RemovingPermanentRestriction, CallNotAllowed} from "contracts/common/L1ContractErrors.sol"; +import {Call} from "contracts/governance/Common.sol"; +import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol"; +import {VerifierParams, FeeParams, PubdataPricingMode} from "contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol"; +import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; +import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; +import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; +import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; +import {StateTransitionManagerTest} from "test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol"; + +contract PermanentRestrictionTest is StateTransitionManagerTest { + ChainAdmin internal chainAdmin; + AccessControlRestriction internal restriction; + PermanentRestriction internal permRestriction; + + address internal owner; + address internal hyperchain; + + function setUp() public { + deploy(); + + createNewChainBridgehub(getDiamondCutData(address(diamondInit))); + + vm.stopPrank(); + + owner = makeAddr("owner"); + hyperchain = chainContractAddress.getHyperchain(chainId); + permRestriction = new PermanentRestriction(owner, bridgehub); + restriction = new AccessControlRestriction(0, owner); + address[] memory restrictions = new address[](1); + restrictions[0] = address(restriction); + chainAdmin = new ChainAdmin(restrictions); + } + + function test_ownerAsAddressZero() public { + vm.expectRevert(ZeroAddress.selector); + permRestriction = new PermanentRestriction(address(0), bridgehub); + } + + function test_allowAdminImplementation(bytes32 implementationHash) public { + vm.expectEmit(true, false, false, true); + emit IPermanentRestriction.AdminImplementationAllowed(implementationHash, true); + + vm.prank(owner); + permRestriction.allowAdminImplementation(implementationHash, true); + } + + function test_setAllowedData(bytes memory data) public { + vm.expectEmit(false, false, false, true); + emit IPermanentRestriction.AllowedDataChanged(data, true); + + vm.prank(owner); + permRestriction.setAllowedData(data, true); + } + + function test_setSelectorIsValidated(bytes4 selector) public { + vm.expectEmit(true, false, false, true); + emit IPermanentRestriction.SelectorValidationChanged(selector, true); + + vm.prank(owner); + permRestriction.setSelectorIsValidated(selector, true); + } + + function test_tryCompareAdminOfAChainIsAddressZero() public { + vm.expectRevert(ChainZeroAddress.selector); + permRestriction.tryCompareAdminOfAChain(address(0), owner); + } + + function test_tryCompareAdminOfAChainNotAHyperchain() public { + vm.expectRevert(); + permRestriction.tryCompareAdminOfAChain(makeAddr("random"), owner); + } + + function test_tryCompareAdminOfAChainNotAnAdmin() public { + vm.expectRevert(abi.encodeWithSelector(NotAnAdmin.selector, IZkSyncHyperchain(hyperchain).getAdmin(), owner)); + permRestriction.tryCompareAdminOfAChain(hyperchain, owner); + } + + function test_tryCompareAdminOfAChain() public { + permRestriction.tryCompareAdminOfAChain(hyperchain, newChainAdmin); + } + + function test_validateCallTooShortData() public { + Call memory call = Call({target: hyperchain, value: 0, data: ""}); + + vm.startPrank(newChainAdmin); + permRestriction.validateCall(call, owner); + vm.stopPrank(); + } + + function test_validateCallSetPendingAdminUnallowedImplementation() public { + Call memory call = Call({ + target: hyperchain, + value: 0, + data: abi.encodeWithSelector(IAdmin.setPendingAdmin.selector, owner) + }); + + vm.expectRevert(abi.encodeWithSelector(UnallowedImplementation.selector, owner.codehash)); + + vm.startPrank(newChainAdmin); + permRestriction.validateCall(call, owner); + vm.stopPrank(); + } + + function test_validateCallSetPendingAdminRemovingPermanentRestriction() public { + vm.prank(owner); + permRestriction.allowAdminImplementation(address(chainAdmin).codehash, true); + + Call memory call = Call({ + target: hyperchain, + value: 0, + data: abi.encodeWithSelector(IAdmin.setPendingAdmin.selector, address(chainAdmin)) + }); + + vm.expectRevert(RemovingPermanentRestriction.selector); + + vm.startPrank(newChainAdmin); + permRestriction.validateCall(call, owner); + vm.stopPrank(); + } + + function test_validateCallSetPendingAdmin() public { + vm.prank(owner); + permRestriction.allowAdminImplementation(address(chainAdmin).codehash, true); + + vm.prank(address(chainAdmin)); + chainAdmin.addRestriction(address(permRestriction)); + + Call memory call = Call({ + target: hyperchain, + value: 0, + data: abi.encodeWithSelector(IAdmin.setPendingAdmin.selector, address(chainAdmin)) + }); + + vm.startPrank(newChainAdmin); + permRestriction.validateCall(call, owner); + vm.stopPrank(); + } + + function test_validateCallNotValidatedSelector() public { + Call memory call = Call({ + target: hyperchain, + value: 0, + data: abi.encodeWithSelector(IAdmin.acceptAdmin.selector) + }); + + vm.startPrank(newChainAdmin); + permRestriction.validateCall(call, owner); + vm.stopPrank(); + } + + function test_validateCallCallNotAllowed() public { + vm.prank(owner); + permRestriction.setSelectorIsValidated(IAdmin.acceptAdmin.selector, true); + Call memory call = Call({ + target: hyperchain, + value: 0, + data: abi.encodeWithSelector(IAdmin.acceptAdmin.selector) + }); + + vm.expectRevert(abi.encodeWithSelector(CallNotAllowed.selector, call.data)); + + vm.startPrank(newChainAdmin); + permRestriction.validateCall(call, owner); + vm.stopPrank(); + } + + function test_validateCall() public { + vm.prank(owner); + permRestriction.setSelectorIsValidated(IAdmin.acceptAdmin.selector, true); + Call memory call = Call({ + target: hyperchain, + value: 0, + data: abi.encodeWithSelector(IAdmin.acceptAdmin.selector) + }); + + vm.prank(owner); + permRestriction.setAllowedData(call.data, true); + + vm.startPrank(newChainAdmin); + permRestriction.validateCall(call, owner); + vm.stopPrank(); + } + + function createNewChainBridgehub(Diamond.DiamondCutData memory _diamondCut) internal { + vm.stopPrank(); + vm.startPrank(address(0)); + bridgehub.addStateTransitionManager(address(chainContractAddress)); + bridgehub.addToken(baseToken); + bridgehub.setSharedBridge(sharedBridge); + bridgehub.createNewChain({ + _chainId: chainId, + _stateTransitionManager: address(chainContractAddress), + _baseToken: baseToken, + _salt: 0, + _admin: newChainAdmin, + _initData: abi.encode(_diamondCut) + }); + } +} diff --git a/l1-contracts/test/foundry/unit/concrete/Governance/Reentrancy.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/Reentrancy.t.sol similarity index 100% rename from l1-contracts/test/foundry/unit/concrete/Governance/Reentrancy.t.sol rename to l1-contracts/test/foundry/unit/concrete/governance/Governance/Reentrancy.t.sol diff --git a/l1-contracts/test/foundry/unit/concrete/Governance/SelfUpgrades.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/SelfUpgrades.t.sol similarity index 97% rename from l1-contracts/test/foundry/unit/concrete/Governance/SelfUpgrades.t.sol rename to l1-contracts/test/foundry/unit/concrete/governance/Governance/SelfUpgrades.t.sol index 04a909f57..a37acf150 100644 --- a/l1-contracts/test/foundry/unit/concrete/Governance/SelfUpgrades.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/governance/Governance/SelfUpgrades.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {Utils} from "../Utils/Utils.sol"; +import {Utils} from "../../Utils/Utils.sol"; import {GovernanceTest} from "./_Governance_Shared.t.sol"; diff --git a/l1-contracts/test/foundry/unit/concrete/Governance/_Governance_Shared.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/_Governance_Shared.t.sol similarity index 93% rename from l1-contracts/test/foundry/unit/concrete/Governance/_Governance_Shared.t.sol rename to l1-contracts/test/foundry/unit/concrete/governance/Governance/_Governance_Shared.t.sol index e7f499254..2a34bc2ff 100644 --- a/l1-contracts/test/foundry/unit/concrete/Governance/_Governance_Shared.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/governance/Governance/_Governance_Shared.t.sol @@ -6,6 +6,7 @@ import {Test} from "forge-std/Test.sol"; import {Governance} from "contracts/governance/Governance.sol"; import {IGovernance} from "contracts/governance/IGovernance.sol"; +import {Call} from "contracts/governance/Common.sol"; import {EventOnFallback} from "contracts/dev-contracts/EventOnFallback.sol"; import {Forwarder} from "contracts/dev-contracts/Forwarder.sol"; import {RevertFallback} from "contracts/dev-contracts/RevertFallback.sol"; @@ -58,8 +59,8 @@ contract GovernanceTest is Test, EventOnFallback { uint256 _value, bytes memory _data ) internal pure returns (IGovernance.Operation memory) { - IGovernance.Call[] memory calls = new IGovernance.Call[](1); - calls[0] = IGovernance.Call({target: _target, value: _value, data: _data}); + Call[] memory calls = new Call[](1); + calls[0] = Call({target: _target, value: _value, data: _data}); return IGovernance.Operation({calls: calls, salt: bytes32(0), predecessor: bytes32(0)}); } diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol index ba69c6bd7..0598779a4 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol @@ -6,6 +6,10 @@ import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; import {Unauthorized, HashMismatch} from "contracts/common/L1ContractErrors.sol"; contract createNewChainTest is StateTransitionManagerTest { + function setUp() public { + deploy(); + } + function test_RevertWhen_InitialDiamondCutHashMismatch() public { Diamond.DiamondCutData memory initialDiamondCutData = getDiamondCutData(sharedBridge); Diamond.DiamondCutData memory correctDiamondCutData = getDiamondCutData(address(diamondInit)); diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/FreezeChain.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/FreezeChain.t.sol index 1bf8c8a40..98dc2661e 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/FreezeChain.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/FreezeChain.t.sol @@ -7,6 +7,10 @@ import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; import {FacetIsFrozen} from "contracts/common/L1ContractErrors.sol"; contract freezeChainTest is StateTransitionManagerTest { + function setUp() public { + deploy(); + } + function test_FreezingChain() public { createNewChain(getDiamondCutData(diamondInit)); diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/RevertBatches.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/RevertBatches.t.sol index 2113f3467..78aef87c3 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/RevertBatches.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/RevertBatches.t.sol @@ -26,6 +26,10 @@ contract revertBatchesTest is StateTransitionManagerTest { ExecutorFacet internal executorFacet; GettersFacet internal gettersFacet; + function setUp() public { + deploy(); + } + function test_SuccessfulBatchReverting() public { createNewChain(getDiamondCutData(diamondInit)); diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetChainCreationParams.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetChainCreationParams.t.sol index 85fa1a316..eeee06beb 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetChainCreationParams.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetChainCreationParams.t.sol @@ -8,6 +8,10 @@ import {IExecutor} from "contracts/state-transition/chain-interfaces/IExecutor.s import {EMPTY_STRING_KECCAK, DEFAULT_L2_LOGS_TREE_ROOT_HASH} from "contracts/common/Config.sol"; contract SetChainCreationParamsTest is StateTransitionManagerTest { + function setUp() public { + deploy(); + } + function test_SettingInitialCutHash() public { bytes32 initialCutHash = keccak256(abi.encode(getDiamondCutData(address(diamondInit)))); address randomDiamondInit = address(0x303030303030303030303); diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetNewVersionUpgrade.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetNewVersionUpgrade.t.sol index ced7e3f7d..ceac175df 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetNewVersionUpgrade.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetNewVersionUpgrade.t.sol @@ -5,6 +5,10 @@ import {StateTransitionManagerTest} from "./_StateTransitionManager_Shared.t.sol import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; contract setNewVersionUpgradeTest is StateTransitionManagerTest { + function setUp() public { + deploy(); + } + function test_SettingNewVersionUpgrade() public { assertEq(chainContractAddress.protocolVersion(), 0, "Initial protocol version is not correct"); diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetUpgradeDiamondCut.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetUpgradeDiamondCut.t.sol index a71f35d2e..32d7614b5 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetUpgradeDiamondCut.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetUpgradeDiamondCut.t.sol @@ -5,6 +5,10 @@ import {StateTransitionManagerTest} from "./_StateTransitionManager_Shared.t.sol import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; contract setUpgradeDiamondCutTest is StateTransitionManagerTest { + function setUp() public { + deploy(); + } + function test_SettingUpgradeDiamondCut() public { assertEq(chainContractAddress.protocolVersion(), 0, "Initial protocol version is not correct"); diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetValidatorTimelock.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetValidatorTimelock.t.sol index d290a8767..2741b3f72 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetValidatorTimelock.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/SetValidatorTimelock.t.sol @@ -4,6 +4,10 @@ pragma solidity 0.8.24; import {StateTransitionManagerTest} from "./_StateTransitionManager_Shared.t.sol"; contract setValidatorTimelockTest is StateTransitionManagerTest { + function setUp() public { + deploy(); + } + function test_SettingValidatorTimelock() public { assertEq( chainContractAddress.validatorTimelock(), diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/StateTransitionOwnerZero.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/StateTransitionOwnerZero.t.sol index d8fb6e187..8b0e0ce09 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/StateTransitionOwnerZero.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/StateTransitionOwnerZero.t.sol @@ -8,6 +8,10 @@ import {StateTransitionManagerInitializeData, ChainCreationParams} from "contrac import {ZeroAddress} from "contracts/common/L1ContractErrors.sol"; contract initializingSTMOwnerZeroTest is StateTransitionManagerTest { + function setUp() public { + deploy(); + } + function test_InitializingSTMWithGovernorZeroShouldRevert() public { ChainCreationParams memory chainCreationParams = ChainCreationParams({ genesisUpgrade: address(genesisUpgradeContract), diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol index 999336642..918cfa476 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol @@ -7,6 +7,7 @@ import {Test} from "forge-std/Test.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol"; import {Utils} from "foundry-test/unit/concrete/Utils/Utils.sol"; +import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {UtilsFacet} from "foundry-test/unit/concrete/Utils/UtilsFacet.sol"; import {AdminFacet} from "contracts/state-transition/chain-deps/facets/Admin.sol"; import {ExecutorFacet} from "contracts/state-transition/chain-deps/facets/Executor.sol"; @@ -24,7 +25,7 @@ contract StateTransitionManagerTest is Test { StateTransitionManager internal stateTransitionManager; StateTransitionManager internal chainContractAddress; GenesisUpgrade internal genesisUpgradeContract; - address internal bridgehub; + Bridgehub internal bridgehub; address internal diamondInit; address internal constant governor = address(0x1010101); address internal constant admin = address(0x2020202); @@ -37,12 +38,12 @@ contract StateTransitionManagerTest is Test { Diamond.FacetCut[] internal facetCuts; - function setUp() public { - bridgehub = makeAddr("bridgehub"); + function deploy() public { + bridgehub = new Bridgehub(); newChainAdmin = makeAddr("chainadmin"); - vm.startPrank(bridgehub); - stateTransitionManager = new StateTransitionManager(bridgehub, type(uint256).max); + vm.startPrank(address(bridgehub)); + stateTransitionManager = new StateTransitionManager(address(bridgehub), type(uint256).max); diamondInit = address(new DiamondInit()); genesisUpgradeContract = new GenesisUpgrade(); @@ -129,7 +130,7 @@ contract StateTransitionManagerTest is Test { function createNewChain(Diamond.DiamondCutData memory _diamondCut) internal { vm.stopPrank(); - vm.startPrank(bridgehub); + vm.startPrank(address(bridgehub)); chainContractAddress.createNewChain({ _chainId: chainId, From 0fa0fa21edaeba5c4ab382debfef26a45a7fc052 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Fri, 6 Sep 2024 13:39:48 +0200 Subject: [PATCH 046/183] foundry tests pass --- .../unit/concrete/Bridgehub/experimental_bridge.t.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol index a3867021c..a636b2033 100644 --- a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol @@ -340,11 +340,11 @@ contract ExperimentalBridgeTest is Test { } function test_addToken_cannotBeCalledByRandomAddress(address randomAddress, address randomCaller, uint256 randomValue) public useRandomToken(randomValue) { - vm.assume(randomAddress != bridgeOwner); - vm.assume(randomAddress != bridgeHub.admin()); + vm.assume(randomCaller != bridgeOwner); + vm.assume(randomCaller != bridgeHub.admin()); vm.prank(randomCaller); - vm.expectRevert(bytes("Bridgehub: not owner or admin")); + vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, randomCaller)); bridgeHub.addToken(randomAddress); assertTrue(!bridgeHub.tokenIsRegistered(randomAddress), "This random address is not registered as a token"); From 00ddc066bb4c1e06e188745866fc7b11dc86cd03 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Fri, 6 Sep 2024 13:41:50 +0200 Subject: [PATCH 047/183] fix compile for registry --- l2-contracts/contracts/ConsensusRegistry.sol | 2 +- l2-contracts/contracts/interfaces/IConsensusRegistry.sol | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/l2-contracts/contracts/ConsensusRegistry.sol b/l2-contracts/contracts/ConsensusRegistry.sol index 6a4a67bde..de5af6340 100644 --- a/l2-contracts/contracts/ConsensusRegistry.sol +++ b/l2-contracts/contracts/ConsensusRegistry.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity 0.8.24; import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable-v4/access/Ownable2StepUpgradeable.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable-v4/proxy/utils/Initializable.sol"; diff --git a/l2-contracts/contracts/interfaces/IConsensusRegistry.sol b/l2-contracts/contracts/interfaces/IConsensusRegistry.sol index e3ddd118a..a5e017484 100644 --- a/l2-contracts/contracts/interfaces/IConsensusRegistry.sol +++ b/l2-contracts/contracts/interfaces/IConsensusRegistry.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT - -pragma solidity 0.8.20; +// 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; /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev From ef3353982c5bec076d0812a53649f19da76720ed Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Fri, 6 Sep 2024 13:44:44 +0200 Subject: [PATCH 048/183] lint --- .../unit/concrete/Bridgehub/experimental_bridge.t.sol | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol index a636b2033..910350041 100644 --- a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol @@ -339,7 +339,11 @@ contract ExperimentalBridgeTest is Test { bridgeHub.addToken(randomAddress); } - function test_addToken_cannotBeCalledByRandomAddress(address randomAddress, address randomCaller, uint256 randomValue) public useRandomToken(randomValue) { + function test_addToken_cannotBeCalledByRandomAddress( + address randomAddress, + address randomCaller, + uint256 randomValue + ) public useRandomToken(randomValue) { vm.assume(randomCaller != bridgeOwner); vm.assume(randomCaller != bridgeHub.admin()); From 5e6211a5d41232008059c20faaf2e929ca4c8abc Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Tue, 10 Sep 2024 12:48:04 -0300 Subject: [PATCH 049/183] 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 050/183] 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 051/183] 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 052/183] 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 053/183] 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 054/183] 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 055/183] 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 056/183] 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 cc3b2ac5dcad7ee05daf30ca7f91a74d7b8a09fd Mon Sep 17 00:00:00 2001 From: kelemeno <34402761+kelemeno@users.noreply.github.com> Date: Tue, 10 Sep 2024 22:46:56 +0100 Subject: [PATCH 057/183] chore: merge main (#790) Signed-off-by: Danil Co-authored-by: Danil Co-authored-by: Vlad Bochok <41153528+vladbochok@users.noreply.github.com> --- .gitignore | 2 + .../deploy-scripts/DeployL2Contracts.sol | 54 ++++-- .../dev/SetupLegacyBridge.s.sol | 155 ++++++++++++++++++ .../test/unit_tests/custom_base_token.spec.ts | 3 +- .../unit_tests/l1_shared_bridge_test.spec.ts | 6 +- .../test/unit_tests/l2-upgrade.test.spec.ts | 2 +- .../test/unit_tests/legacy_era_test.spec.ts | 2 +- .../test/unit_tests/mailbox_test.spec.ts | 2 +- .../test/unit_tests/proxy_test.spec.ts | 6 +- 9 files changed, 210 insertions(+), 22 deletions(-) create mode 100644 l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol diff --git a/.gitignore b/.gitignore index 21c173828..21516dc8e 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ l1-contracts/script-config/* l1-contracts/script-out/* !l1-contracts/script-out/.gitkeep *.timestamp +l1-contracts/test/foundry/l1/integration/deploy-scripts/script-out/* +l1-contracts/zkout/* diff --git a/l1-contracts/deploy-scripts/DeployL2Contracts.sol b/l1-contracts/deploy-scripts/DeployL2Contracts.sol index 1a02fd391..fb3f35024 100644 --- a/l1-contracts/deploy-scripts/DeployL2Contracts.sol +++ b/l1-contracts/deploy-scripts/DeployL2Contracts.sol @@ -46,12 +46,20 @@ contract DeployL2Script is Script { } function run() public { + deploy(false); + } + + function runWithLegacyBridge() public { + deploy(true); + } + + function deploy(bool legacyBridge) public { initializeConfig(); - loadContracts(); + loadContracts(legacyBridge); deployFactoryDeps(); deploySharedBridge(); - deploySharedBridgeProxy(); + deploySharedBridgeProxy(legacyBridge); initializeChain(); deployForceDeployer(); deployConsensusRegistry(); @@ -60,13 +68,21 @@ contract DeployL2Script is Script { saveOutput(); } + function runDeployLegacySharedBridge() public { + deploySharedBridge(true); + } + function runDeploySharedBridge() public { + deploySharedBridge(false); + } + + function deploySharedBridge(bool legacyBridge) internal { initializeConfig(); - loadContracts(); + loadContracts(legacyBridge); deployFactoryDeps(); deploySharedBridge(); - deploySharedBridgeProxy(); + deploySharedBridgeProxy(legacyBridge); initializeChain(); saveOutput(); @@ -74,7 +90,7 @@ contract DeployL2Script is Script { function runDefaultUpgrader() public { initializeConfig(); - loadContracts(); + loadContracts(false); deployForceDeployer(); @@ -83,7 +99,7 @@ contract DeployL2Script is Script { function runDeployConsensusRegistry() public { initializeConfig(); - loadContracts(); + loadContracts(false); deployConsensusRegistry(); deployConsensusRegistryProxy(); @@ -91,7 +107,7 @@ contract DeployL2Script is Script { saveOutput(); } - function loadContracts() internal { + function loadContracts(bool legacyBridge) internal { //HACK: Meanwhile we are not integrated foundry zksync we use contracts that has been built using hardhat contracts.l2StandardErc20FactoryBytecode = Utils.readHardhatBytecode( "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.json" @@ -103,9 +119,16 @@ contract DeployL2Script is Script { "/../l2-contracts/artifacts-zk/contracts/bridge/L2StandardERC20.sol/L2StandardERC20.json" ); - contracts.l2SharedBridgeBytecode = Utils.readFoundryBytecode( - "/../l2-contracts/zkout/L2SharedBridge.sol/L2SharedBridge.json" - ); + if (legacyBridge) { + contracts.l2SharedBridgeBytecode = Utils.readHardhatBytecode( + "/../l2-contracts/artifacts-zk/contracts/dev-contracts/DevL2SharedBridge.sol/DevL2SharedBridge.json" + ); + } else { + contracts.l2SharedBridgeBytecode = Utils.readHardhatBytecode( + "/../l2-contracts/zkout/L2SharedBridge.sol/L2SharedBridge.json" + ); + } + contracts.l2SharedBridgeProxyBytecode = Utils.readHardhatBytecode( "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json" ); @@ -186,13 +209,20 @@ contract DeployL2Script is Script { }); } - function deploySharedBridgeProxy() internal { + function deploySharedBridgeProxy(bool legacyBridge) internal { address l2GovernorAddress = AddressAliasHelper.applyL1ToL2Alias(config.governance); bytes32 l2StandardErc20BytecodeHash = L2ContractHelper.hashL2Bytecode(contracts.beaconProxy); + string memory functionSignature; + + if (legacyBridge) { + functionSignature = "initializeDevBridge(address,address,bytes32,address)"; + } else { + functionSignature = "initialize(address,address,bytes32,address)"; + } // solhint-disable-next-line func-named-parameters bytes memory proxyInitializationParams = abi.encodeWithSignature( - "initialize(address,address,bytes32,address)", + functionSignature, config.l1SharedBridgeProxy, config.erc20BridgeProxy, l2StandardErc20BytecodeHash, diff --git a/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol new file mode 100644 index 000000000..301bfd2c8 --- /dev/null +++ b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Script} from "forge-std/Script.sol"; +import {stdToml} from "forge-std/StdToml.sol"; +import {Utils} from "./../Utils.sol"; +import {L1SharedBridge} from "contracts/bridge/L1SharedBridge.sol"; +import {DummyL1ERC20Bridge} from "contracts/dev-contracts/DummyL1ERC20Bridge.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; + +/// This scripts is only for developer +contract SetupLegacyBridge is Script { + using stdToml for string; + + Config internal config; + Addresses internal addresses; + + struct Config { + uint256 chainId; + address l2SharedBridgeAddress; + bytes32 create2FactorySalt; + } + + struct Addresses { + address create2FactoryAddr; + address bridgehub; + address diamondProxy; + address sharedBridgeProxy; + address transparentProxyAdmin; + address erc20BridgeProxy; + address tokenWethAddress; + address erc20BridgeProxyImpl; + address sharedBridgeProxyImpl; + } + + function run() public { + initializeConfig(); + deploySharedBridgeImplementation(); + upgradeImplementation(addresses.sharedBridgeProxy, addresses.sharedBridgeProxyImpl); + deployDummyErc20Bridge(); + upgradeImplementation(addresses.erc20BridgeProxy, addresses.erc20BridgeProxyImpl); + setParamsForDummyBridge(); + } + + function initializeConfig() internal { + string memory root = vm.projectRoot(); + string memory path = string.concat(root, "/script-config/setup-legacy-bridge.toml"); + string memory toml = vm.readFile(path); + + addresses.bridgehub = toml.readAddress("$.bridgehub"); + addresses.diamondProxy = toml.readAddress("$.diamond_proxy"); + addresses.sharedBridgeProxy = toml.readAddress("$.shared_bridge_proxy"); + addresses.transparentProxyAdmin = toml.readAddress("$.transparent_proxy_admin"); + addresses.erc20BridgeProxy = toml.readAddress("$.erc20bridge_proxy"); + addresses.tokenWethAddress = toml.readAddress("$.token_weth_address"); + addresses.create2FactoryAddr = toml.readAddress("$.create2factory_addr"); + config.chainId = toml.readUint("$.chain_id"); + config.l2SharedBridgeAddress = toml.readAddress("$.l2shared_bridge_address"); + config.create2FactorySalt = toml.readBytes32("$.create2factory_salt"); + } + + // We need to deploy new shared bridge for changing chain id and diamond proxy address + function deploySharedBridgeImplementation() internal { + bytes memory bytecode = abi.encodePacked( + type(L1SharedBridge).creationCode, + // solhint-disable-next-line func-named-parameters + abi.encode(addresses.tokenWethAddress, addresses.bridgehub, config.chainId, addresses.diamondProxy) + ); + + address contractAddress = deployViaCreate2(bytecode); + addresses.sharedBridgeProxyImpl = contractAddress; + } + + function deployDummyErc20Bridge() internal { + bytes memory bytecode = abi.encodePacked( + type(DummyL1ERC20Bridge).creationCode, + // solhint-disable-next-line func-named-parameters + abi.encode(addresses.sharedBridgeProxy) + ); + address contractAddress = deployViaCreate2(bytecode); + addresses.erc20BridgeProxyImpl = contractAddress; + } + + function upgradeImplementation(address proxy, address implementation) internal { + bytes memory proxyAdminUpgradeData = abi.encodeCall( + ProxyAdmin.upgrade, + (ITransparentUpgradeableProxy(proxy), implementation) + ); + ProxyAdmin _proxyAdmin = ProxyAdmin(addresses.transparentProxyAdmin); + address governance = _proxyAdmin.owner(); + + Utils.executeUpgrade({ + _governor: address(governance), + _salt: bytes32(0), + _target: address(addresses.transparentProxyAdmin), + _data: proxyAdminUpgradeData, + _value: 0, + _delay: 0 + }); + } + + function setParamsForDummyBridge() internal { + (address l2TokenBeacon, bytes32 l2TokenBeaconHash) = calculateTokenBeaconAddress(); + DummyL1ERC20Bridge bridge = DummyL1ERC20Bridge(addresses.erc20BridgeProxy); + bridge.setValues(config.l2SharedBridgeAddress, l2TokenBeacon, l2TokenBeaconHash); + } + + function calculateTokenBeaconAddress() + internal + returns (address tokenBeaconAddress, bytes32 tokenBeaconBytecodeHash) + { + bytes memory l2StandardTokenCode = Utils.readHardhatBytecode( + "/../l2-contracts/artifacts-zk/contracts/bridge/L2StandardERC20.sol/L2StandardERC20.json" + ); + (address l2StandardToken, ) = calculateL2Create2Address( + config.l2SharedBridgeAddress, + l2StandardTokenCode, + bytes32(0), + "" + ); + + bytes memory beaconProxy = Utils.readHardhatBytecode( + "/../l2-contracts/artifacts-zk/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.json" + ); + + (tokenBeaconAddress, tokenBeaconBytecodeHash) = calculateL2Create2Address( + config.l2SharedBridgeAddress, + beaconProxy, + bytes32(0), + abi.encode(l2StandardToken) + ); + } + + function calculateL2Create2Address( + address sender, + bytes memory bytecode, + bytes32 create2salt, + bytes memory constructorargs + ) internal returns (address create2Address, bytes32 bytecodeHash) { + bytecodeHash = L2ContractHelper.hashL2Bytecode(bytecode); + + create2Address = L2ContractHelper.computeCreate2Address( + sender, + create2salt, + bytecodeHash, + keccak256(constructorargs) + ); + } + + function deployViaCreate2(bytes memory _bytecode) internal returns (address) { + return Utils.deployViaCreate2(_bytecode, config.create2FactorySalt, addresses.create2FactoryAddr); + } +} diff --git a/l1-contracts/test/unit_tests/custom_base_token.spec.ts b/l1-contracts/test/unit_tests/custom_base_token.spec.ts index 464298482..b7dce29b1 100644 --- a/l1-contracts/test/unit_tests/custom_base_token.spec.ts +++ b/l1-contracts/test/unit_tests/custom_base_token.spec.ts @@ -147,7 +147,8 @@ describe("Custom base token chain and bridge tests", () => { const revertReason = await getCallRevertReason( l1SharedBridge.connect(randomSigner).finalizeWithdrawal(chainId, 0, 0, 0, "0x", []) ); - expect(revertReason).contains("MalformedMessage"); + console.log(revertReason); + expect(revertReason).contains("L2WithdrawalMessageWrongLength"); }); it("Should revert on finalizing a withdrawal with wrong function selector", async () => { diff --git a/l1-contracts/test/unit_tests/l1_shared_bridge_test.spec.ts b/l1-contracts/test/unit_tests/l1_shared_bridge_test.spec.ts index 31475e241..fb5cf437d 100644 --- a/l1-contracts/test/unit_tests/l1_shared_bridge_test.spec.ts +++ b/l1-contracts/test/unit_tests/l1_shared_bridge_test.spec.ts @@ -129,7 +129,7 @@ describe("Shared Bridge tests", () => { const revertReason = await getCallRevertReason( l1SharedBridge.connect(randomSigner).finalizeWithdrawal(chainId, 0, 0, 0, "0x", [ethers.constants.HashZero]) ); - expect(revertReason).contains("MalformedMessage"); + expect(revertReason).contains("L2WithdrawalMessageWrongLength"); }); it("Should revert on finalizing a withdrawal with wrong message length", async () => { @@ -145,7 +145,7 @@ describe("Shared Bridge tests", () => { [ethers.constants.HashZero] ) ); - expect(revertReason).contains("MalformedMessage"); + expect(revertReason).contains("L2WithdrawalMessageWrongLength"); }); it("Should revert on finalizing a withdrawal with wrong function selector", async () => { @@ -183,7 +183,7 @@ describe("Shared Bridge tests", () => { const revertReason = await getCallRevertReason( l1SharedBridge.connect(randomSigner).finalizeWithdrawal(chainId, 0, 0, 0, "0x", [ethers.constants.HashZero]) ); - expect(revertReason).contains("MalformedMessage"); + expect(revertReason).contains("L2WithdrawalMessageWrongLength"); }); it("Should revert on finalizing a withdrawal with wrong function signature", async () => { 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 b5d97bf7d..1f6af8899 100644 --- a/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts +++ b/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts @@ -42,7 +42,7 @@ import { } from "./utils"; import { packSemver, unpackStringSemVer, addToProtocolVersion } from "../../scripts/utils"; -describe.only("L2 upgrade test", function () { +describe("L2 upgrade test", function () { let proxyExecutor: ExecutorFacet; let proxyAdmin: AdminFacet; let proxyGetters: GettersFacet; diff --git a/l1-contracts/test/unit_tests/legacy_era_test.spec.ts b/l1-contracts/test/unit_tests/legacy_era_test.spec.ts index 0f4f26bd9..44469df8c 100644 --- a/l1-contracts/test/unit_tests/legacy_era_test.spec.ts +++ b/l1-contracts/test/unit_tests/legacy_era_test.spec.ts @@ -164,7 +164,7 @@ describe("Legacy Era tests", function () { const revertReason = await getCallRevertReason( l1ERC20Bridge.connect(randomSigner).finalizeWithdrawal(0, 0, 0, "0x", [ethers.constants.HashZero]) ); - expect(revertReason).contains("MalformedMessage"); + expect(revertReason).contains("L2WithdrawalMessageWrongLength"); }); it("Should revert on finalizing a withdrawal with wrong function signature", async () => { diff --git a/l1-contracts/test/unit_tests/mailbox_test.spec.ts b/l1-contracts/test/unit_tests/mailbox_test.spec.ts index 5bb874381..230f4e46e 100644 --- a/l1-contracts/test/unit_tests/mailbox_test.spec.ts +++ b/l1-contracts/test/unit_tests/mailbox_test.spec.ts @@ -105,7 +105,7 @@ describe("Mailbox tests", function () { ) ); - expect(revertReason).contains("MalformedBytecode"); + expect(revertReason).contains("LengthIsNotDivisibleBy32"); }); it("Should not accept bytecode of even length in words", async () => { diff --git a/l1-contracts/test/unit_tests/proxy_test.spec.ts b/l1-contracts/test/unit_tests/proxy_test.spec.ts index e63abe0bb..5336f3266 100644 --- a/l1-contracts/test/unit_tests/proxy_test.spec.ts +++ b/l1-contracts/test/unit_tests/proxy_test.spec.ts @@ -134,14 +134,14 @@ describe("Diamond proxy tests", function () { const proxyAsERC20 = TestnetERC20TokenFactory.connect(proxy.address, proxy.signer); const revertReason = await getCallRevertReason(proxyAsERC20.transfer(proxyAsERC20.address, 0)); - expect(revertReason).contains("InvalidSelector"); + expect(revertReason).contains("F"); }); it("check that proxy reject data with no selector", async () => { const dataWithoutSelector = "0x1122"; const revertReason = await getCallRevertReason(proxy.fallback({ data: dataWithoutSelector })); - expect(revertReason).contains("MalformedCalldata"); + expect(revertReason).contains("Ut"); }); it("should freeze the diamond storage", async () => { @@ -178,7 +178,7 @@ describe("Diamond proxy tests", function () { data: executorFacetSelector3 + "0000000000000000000000000000000000000000000000000000000000000000", }) ); - expect(revertReason).contains("FacetIsFrozen"); + expect(revertReason).contains("q1"); }); it("should be able to call an unfreezable facet when diamondStorage is frozen", async () => { 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 058/183] 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 059/183] [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 060/183] [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 061/183] 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 062/183] 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 063/183] 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 064/183] 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); } From 966dc1281d36c95ad285d2ab105752c2916669c5 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 25 Sep 2024 13:12:06 +0200 Subject: [PATCH 065/183] Optimize EvmGasManager --- .../contracts/AccountCodeStorage.sol | 3 +- system-contracts/contracts/EvmGasManager.sol | 90 ++++++++----------- system-contracts/contracts/EvmInterpreter.yul | 90 +++---------------- .../contracts/interfaces/IEvmGasManager.sol | 4 +- .../EvmInterpreterFunctions.template.yul | 45 ++-------- 5 files changed, 59 insertions(+), 173 deletions(-) diff --git a/system-contracts/contracts/AccountCodeStorage.sol b/system-contracts/contracts/AccountCodeStorage.sol index 15ccdd9ce..52879df1f 100644 --- a/system-contracts/contracts/AccountCodeStorage.sol +++ b/system-contracts/contracts/AccountCodeStorage.sol @@ -115,8 +115,7 @@ 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; - } - else if (Utils.isCodeHashEVM(codeHash)) { + } else if (Utils.isCodeHashEVM(codeHash)) { codeHash = DEPLOYER_SYSTEM_CONTRACT.evmCodeHash(account); } diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index 398735247..bf9585b24 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; -import "./libraries/Utils.sol"; +import {Utils} from "./libraries/Utils.sol"; import {ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "./Constants.sol"; import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; @@ -12,16 +12,19 @@ import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; // We consider all the contracts (including system ones) as warm. uint160 constant PRECOMPILES_END = 0xffff; -uint256 constant INF_PASS_GAS = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - // 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; + +uint256 constant EVM_GAS_SLOT = 4; +uint256 constant EVM_AUX_DATA_SLOT = 5; +uint256 constant EVM_ACTIVE_FRAME_FLAG = 1 << 1; contract EvmGasManager { modifier onlySystemEvm() { + require(SystemContractHelper.isSystemCall(), "This method requires system call flag"); + // cache use is safe since we do not support SELFDESTRUCT uint256 transient_slot = IS_ACCOUNT_EVM_PREFIX | uint256(uint160(msg.sender)); bool isEVM; @@ -42,7 +45,6 @@ contract EvmGasManager { } require(isEVM, "only system evm"); - require(SystemContractHelper.isSystemCall(), "This method requires system call flag"); _; } @@ -51,17 +53,17 @@ contract EvmGasManager { */ function warmAccount(address account) external payable onlySystemEvm returns (bool wasWarm) { if (uint160(account) < PRECOMPILES_END) return true; - uint256 transient_slot = IS_ACCOUNT_WARM_PREFIX | uint256(uint160(account)); assembly { wasWarm := tload(transient_slot) - } - if (!wasWarm) { - assembly { + if iszero(wasWarm) { tstore(transient_slot, 1) } + + mstore(0x0, wasWarm) + return(0x0, 0x20) } } @@ -72,10 +74,10 @@ contract EvmGasManager { mstore(0, prefix) mstore(0x20, _slot) transient_slot := keccak256(0, 64) - } - - assembly { isWarm := tload(transient_slot) + + mstore(0x0, isWarm) + return(0x0, 0x20) } } @@ -89,69 +91,55 @@ contract EvmGasManager { mstore(0, prefix) mstore(0x20, _slot) transient_slot := keccak256(0, 64) - } - assembly { isWarm := tload(transient_slot) - } - if (isWarm) { - assembly { - originalValue := tload(add(transient_slot, 1)) - } - } else { - originalValue = _currentValue; - - assembly { + switch isWarm + case 0 { + originalValue := _currentValue tstore(transient_slot, 1) tstore(add(transient_slot, 1), originalValue) } + default { + originalValue := tload(add(transient_slot, 1)) + } + + mstore(0x0, isWarm) + mstore(0x20, originalValue) + return(0x0, 0x40) } } /* - 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 and determine if a call is static - 3. calleer calls popEVMFrame to remove the frame + 2. callee calls consumeEvmFrame to get the gas and determine if a call is static, frame is marked as used */ 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) + tstore(EVM_GAS_SLOT, passGas) + tstore(EVM_AUX_DATA_SLOT, or(isStatic, EVM_ACTIVE_FRAME_FLAG)) } } - function consumeEvmFrame() external onlySystemEvm returns (uint256 passGas, bool isStatic) { - uint256 stackDepth; + function consumeEvmFrame() external onlySystemEvm returns (uint256 passGas, uint256 auxDataRes) { assembly { - stackDepth := tload(EVM_STACK_SLOT) - } - if (stackDepth == 0) return (INF_PASS_GAS, false); + let auxData := tload(EVM_AUX_DATA_SLOT) + let isFrameActive := and(auxData, EVM_ACTIVE_FRAME_FLAG) - assembly { - 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 - } - } + if isFrameActive { + passGas := tload(EVM_GAS_SLOT) + auxDataRes := auxData - function popEVMFrame() external onlySystemEvm { - uint256 stackDepth; - assembly { - stackDepth := tload(EVM_STACK_SLOT) - } - require(stackDepth != 0); - assembly { - tstore(EVM_STACK_SLOT, sub(stackDepth, 1)) + tstore(EVM_AUX_DATA_SLOT, 0) // mark as consumed + } + + mstore(0x0, passGas) + mstore(0x20, auxDataRes) + return(0x0, 0x40) } } } diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmInterpreter.yul index b16daad6a..3e35f5d5e 100644 --- a/system-contracts/contracts/EvmInterpreter.yul +++ b/system-contracts/contracts/EvmInterpreter.yul @@ -368,7 +368,7 @@ object "EVMInterpreter" { } function consumeEvmFrame() -> passGas, isStatic, callerEVM { - // function consumeEvmFrame() external returns (uint256 passGas, bool isStatic) + // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) mstore(0, 0x04C14E9E00000000000000000000000000000000000000000000000000000000) let farCallAbi := getFarCallABI( @@ -393,11 +393,12 @@ object "EVMInterpreter" { returndatacopy(0,0,64) - passGas := mload(0) - isStatic := mload(32) + let auxData := mload(32) + callerEVM := gt(auxData, 1) - if iszero(eq(passGas, INF_PASS_GAS())) { - callerEVM := true + if callerEVM { + isStatic := and(auxData, 1) + passGas := mload(0) } } @@ -774,33 +775,6 @@ 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() - - 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 @@ -941,7 +915,6 @@ object "EVMInterpreter" { 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) @@ -998,7 +971,6 @@ object "EVMInterpreter" { _pushEVMFrame(gasToPassNew, isStatic) success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - _popEVMFrame() } } default { @@ -1139,8 +1111,6 @@ object "EVMInterpreter" { let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - _popEVMFrame() - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) switch iszero(precompileCost) case 1 { @@ -1182,7 +1152,6 @@ object "EVMInterpreter" { success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) - _popEVMFrame() } } @@ -1272,8 +1241,6 @@ object "EVMInterpreter" { let gasUsed := sub(gasForTheCall, gasLeft) evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - _popEVMFrame() - let back // skipping check since we pushed exactly 4 items earlier @@ -3234,7 +3201,7 @@ object "EVMInterpreter" { } function consumeEvmFrame() -> passGas, isStatic, callerEVM { - // function consumeEvmFrame() external returns (uint256 passGas, bool isStatic) + // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) mstore(0, 0x04C14E9E00000000000000000000000000000000000000000000000000000000) let farCallAbi := getFarCallABI( @@ -3259,11 +3226,12 @@ object "EVMInterpreter" { returndatacopy(0,0,64) - passGas := mload(0) - isStatic := mload(32) + let auxData := mload(32) + callerEVM := gt(auxData, 1) - if iszero(eq(passGas, INF_PASS_GAS())) { - callerEVM := true + if callerEVM { + isStatic := and(auxData, 1) + passGas := mload(0) } } @@ -3640,33 +3608,6 @@ 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() - - 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 @@ -3807,7 +3748,6 @@ object "EVMInterpreter" { 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) @@ -3864,7 +3804,6 @@ object "EVMInterpreter" { _pushEVMFrame(gasToPassNew, isStatic) success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - _popEVMFrame() } } default { @@ -4005,8 +3944,6 @@ object "EVMInterpreter" { let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - _popEVMFrame() - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) switch iszero(precompileCost) case 1 { @@ -4048,7 +3985,6 @@ object "EVMInterpreter" { success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) - _popEVMFrame() } } @@ -4138,8 +4074,6 @@ object "EVMInterpreter" { let gasUsed := sub(gasForTheCall, gasLeft) evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - _popEVMFrame() - let back // skipping check since we pushed exactly 4 items earlier diff --git a/system-contracts/contracts/interfaces/IEvmGasManager.sol b/system-contracts/contracts/interfaces/IEvmGasManager.sol index 63c42ff2f..426deb5bc 100644 --- a/system-contracts/contracts/interfaces/IEvmGasManager.sol +++ b/system-contracts/contracts/interfaces/IEvmGasManager.sol @@ -10,7 +10,5 @@ interface IEvmGasManager { function pushEVMFrame(uint256 _passGas, bool _isStatic) external; - function consumeEvmFrame() external returns (uint256 passGas, bool isStatic); - - function popEVMFrame() external; + function consumeEvmFrame() external returns (uint256 passGas, uint256 auxData); } diff --git a/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul b/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul index 4d2f6f3aa..1e4ec38f7 100644 --- a/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul +++ b/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul @@ -286,7 +286,7 @@ function getDeployedBytecode() { } function consumeEvmFrame() -> passGas, isStatic, callerEVM { - // function consumeEvmFrame() external returns (uint256 passGas, bool isStatic) + // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) mstore(0, 0x04C14E9E00000000000000000000000000000000000000000000000000000000) let farCallAbi := getFarCallABI( @@ -311,11 +311,12 @@ function consumeEvmFrame() -> passGas, isStatic, callerEVM { returndatacopy(0,0,64) - passGas := mload(0) - isStatic := mload(32) + let auxData := mload(32) + callerEVM := gt(auxData, 1) - if iszero(eq(passGas, INF_PASS_GAS())) { - callerEVM := true + if callerEVM { + isStatic := and(auxData, 1) + passGas := mload(0) } } @@ -692,33 +693,6 @@ function _pushEVMFrame(_passGas, _isStatic) { } } -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 @@ -859,7 +833,6 @@ function performStaticCall(oldSp,evmGasLeft) -> extraCost, sp { 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) @@ -916,7 +889,6 @@ function _performCall(addr,gasToPass,value,argsOffset,argsSize,retOffset,retSize _pushEVMFrame(gasToPassNew, isStatic) success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - _popEVMFrame() } } default { @@ -1057,8 +1029,6 @@ function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - _popEVMFrame() - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) switch iszero(precompileCost) case 1 { @@ -1100,7 +1070,6 @@ function _performStaticCall( success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) - _popEVMFrame() } } @@ -1190,8 +1159,6 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO let gasUsed := sub(gasForTheCall, gasLeft) evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - _popEVMFrame() - let back // skipping check since we pushed exactly 4 items earlier From a0448c990f94c2001a11ed8ba963eb41affa4835 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 25 Sep 2024 14:40:03 +0200 Subject: [PATCH 066/183] Make EvmGasManager methods payable --- system-contracts/contracts/EvmGasManager.sol | 4 ++-- system-contracts/contracts/interfaces/IEvmGasManager.sol | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index bf9585b24..50cab37c7 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -118,14 +118,14 @@ contract EvmGasManager { 2. callee calls consumeEvmFrame to get the gas and determine if a call is static, frame is marked as used */ - function pushEVMFrame(uint256 passGas, bool isStatic) external onlySystemEvm { + function pushEVMFrame(uint256 passGas, bool isStatic) external payable onlySystemEvm { assembly { tstore(EVM_GAS_SLOT, passGas) tstore(EVM_AUX_DATA_SLOT, or(isStatic, EVM_ACTIVE_FRAME_FLAG)) } } - function consumeEvmFrame() external onlySystemEvm returns (uint256 passGas, uint256 auxDataRes) { + function consumeEvmFrame() external payable onlySystemEvm returns (uint256 passGas, uint256 auxDataRes) { assembly { let auxData := tload(EVM_AUX_DATA_SLOT) let isFrameActive := and(auxData, EVM_ACTIVE_FRAME_FLAG) diff --git a/system-contracts/contracts/interfaces/IEvmGasManager.sol b/system-contracts/contracts/interfaces/IEvmGasManager.sol index 426deb5bc..646d7bf24 100644 --- a/system-contracts/contracts/interfaces/IEvmGasManager.sol +++ b/system-contracts/contracts/interfaces/IEvmGasManager.sol @@ -8,7 +8,7 @@ interface IEvmGasManager { function warmSlot(uint256 _slot, uint256 _currentValue) external payable returns (bool, uint256); - function pushEVMFrame(uint256 _passGas, bool _isStatic) external; + function pushEVMFrame(uint256 _passGas, bool _isStatic) external payable; - function consumeEvmFrame() external returns (uint256 passGas, uint256 auxData); + function consumeEvmFrame() external payable returns (uint256 passGas, uint256 auxData); } From ea5a158d5d4348eefb819a1b603a2d6e5086e106 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 25 Sep 2024 16:18:55 +0200 Subject: [PATCH 067/183] Use custom errors and optimize call inside EvmGasManager --- system-contracts/contracts/EvmGasManager.sol | 34 +++++++++++++++---- .../contracts/SystemContractErrors.sol | 2 ++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index 50cab37c7..b98bc9228 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -8,6 +8,7 @@ import {Utils} from "./libraries/Utils.sol"; import {ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "./Constants.sol"; import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; +import {SystemCallFlagRequired, CallerMustBeEvmContract} from "./SystemContractErrors.sol"; // We consider all the contracts (including system ones) as warm. uint160 constant PRECOMPILES_END = 0xffff; @@ -23,28 +24,47 @@ uint256 constant EVM_ACTIVE_FRAME_FLAG = 1 << 1; contract EvmGasManager { modifier onlySystemEvm() { - require(SystemContractHelper.isSystemCall(), "This method requires system call flag"); + if (!SystemContractHelper.isSystemCall()) { + revert SystemCallFlagRequired(); + } // cache use is safe since we do not support SELFDESTRUCT - uint256 transient_slot = IS_ACCOUNT_EVM_PREFIX | uint256(uint160(msg.sender)); + uint256 _sender = uint256(uint160(msg.sender)); + uint256 transient_slot = IS_ACCOUNT_EVM_PREFIX | _sender; bool isEVM; assembly { isEVM := tload(transient_slot) } if (!isEVM) { - bytes32 bytecodeHash = ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.getRawCodeHash(msg.sender); - isEVM = Utils.isCodeHashEVM(bytecodeHash); + address to = address(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT); + bytes32 rawCodeHash; + assembly { + // function getRawCodeHash(address _address) public view returns (bytes32 codeHash) + mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) + mstore(4, _sender) + + let success := staticcall(gas(), to, 0, 36, 0, 32) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + rawCodeHash := mload(0) + } + + isEVM = Utils.isCodeHashEVM(rawCodeHash); if (isEVM) { - if (!Utils.isContractConstructing(bytecodeHash)) { + if (!Utils.isContractConstructing(rawCodeHash)) { assembly { tstore(transient_slot, isEVM) } } + } else { + revert CallerMustBeEvmContract(); } } - - require(isEVM, "only system evm"); _; } diff --git a/system-contracts/contracts/SystemContractErrors.sol b/system-contracts/contracts/SystemContractErrors.sol index b5dfc8276..49dee4655 100644 --- a/system-contracts/contracts/SystemContractErrors.sol +++ b/system-contracts/contracts/SystemContractErrors.sol @@ -6,6 +6,8 @@ pragma solidity ^0.8.20; error AddressHasNoCode(address); // 0xefce78c7 error CallerMustBeBootloader(); +// 0xbe4bf9e4 +error CallerMustBeEvmContract(); // 0xb7549616 error CallerMustBeForceDeployer(); // 0x9eedbd2b From 0b6175e9954f16ae598a55995e50fa6b3270667d Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 25 Sep 2024 16:19:37 +0200 Subject: [PATCH 068/183] Prettier run --- 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 b98bc9228..30bc9f938 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -43,14 +43,14 @@ contract EvmGasManager { // function getRawCodeHash(address _address) public view returns (bytes32 codeHash) mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, _sender) - + let success := staticcall(gas(), to, 0, 36, 0, 32) - + if iszero(success) { // This error should never happen revert(0, 0) } - + rawCodeHash := mload(0) } From 4b55877f55e9b8560028925cda2ae308fd179c21 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 26 Sep 2024 16:33:46 +0200 Subject: [PATCH 069/183] Implement return opcode hotfix --- system-contracts/contracts/EvmInterpreter.yul | 6 ++++-- .../evm-interpreter/EvmInterpreterLoop.template.yul | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmInterpreter.yul index b16daad6a..fede9314c 100644 --- a/system-contracts/contracts/EvmInterpreter.yul +++ b/system-contracts/contracts/EvmInterpreter.yul @@ -2852,9 +2852,10 @@ object "EVMInterpreter" { size, sp := popStackItemWithoutCheck(sp) checkOverflow(offset,size, evmGasLeft) - checkMemOverflowByOffset(add(offset,size), evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + checkMemOverflowByOffset(add(offset,size), evmGasLeft) + returnLen := size // Don't check overflow here since previous checks are enough to ensure this is safe @@ -5718,9 +5719,10 @@ object "EVMInterpreter" { size, sp := popStackItemWithoutCheck(sp) checkOverflow(offset,size, evmGasLeft) - checkMemOverflowByOffset(add(offset,size), evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + checkMemOverflowByOffset(add(offset,size), evmGasLeft) + returnLen := size // Don't check overflow here since previous checks are enough to ensure this is safe diff --git a/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul b/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul index ae64735c0..4fe751cba 100644 --- a/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul +++ b/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul @@ -1402,9 +1402,10 @@ for { } true { } { size, sp := popStackItemWithoutCheck(sp) checkOverflow(offset,size, evmGasLeft) - checkMemOverflowByOffset(add(offset,size), evmGasLeft) evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) + checkMemOverflowByOffset(add(offset,size), evmGasLeft) + returnLen := size // Don't check overflow here since previous checks are enough to ensure this is safe From 7827bf3c74be6490e0218aa5aeb606ba6919401b Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 9 Oct 2024 17:13:02 +0300 Subject: [PATCH 070/183] chore: Rename interpreter to emulator (#846) --- .../dev-contracts/test/CustomUpgradeTest.sol | 2 +- .../test/ExecutorProvingTest.sol | 6 +-- .../StateTransitionManager.sol | 2 +- .../chain-deps/DiamondInit.sol | 2 +- .../chain-deps/ZkSyncHyperchainStorage.sol | 4 +- .../chain-deps/facets/Executor.sol | 4 +- .../chain-deps/facets/Getters.sol | 4 +- .../chain-interfaces/IDiamondInit.sol | 6 ++- .../chain-interfaces/IGetters.sol | 4 +- .../contracts/upgrades/BaseZkSyncUpgrade.sol | 30 ++++++----- l1-contracts/deploy-scripts/DeployL1.s.sol | 4 +- .../scripts/upgrade-consistency-checker.ts | 8 +-- l1-contracts/scripts/utils.ts | 4 +- l1-contracts/src.ts/deploy-process.ts | 2 +- l1-contracts/src.ts/deploy-test-process.ts | 8 +-- l1-contracts/src.ts/deploy.ts | 14 ++--- l1-contracts/src.ts/diamondCut.ts | 2 +- l1-contracts/src.ts/utils.ts | 14 ++--- .../concrete/DiamondCut/UpgradeLogic.t.sol | 2 +- .../concrete/Executor/ExecutorProof.t.sol | 2 +- .../concrete/Executor/_Executor_Shared.t.sol | 4 +- .../foundry/unit/concrete/Utils/Utils.sol | 10 ++-- .../unit/concrete/Utils/UtilsFacet.sol | 8 +-- .../chain-deps/DiamondInit/Initialize.t.sol | 2 +- .../facets/Admin/ExecuteUpgrade.t.sol | 2 +- .../facets/Getters/_Getters_Shared.t.sol | 4 +- .../test/unit_tests/executor_proof.spec.ts | 4 +- .../test/unit_tests/l2-upgrade.test.spec.ts | 12 ++--- .../test/unit_tests/proxy_test.spec.ts | 2 +- system-contracts/SystemContractsHashes.json | 6 +-- .../{EvmInterpreter.yul => EvmEmulator.yul} | 4 +- .../EvmEmulator.template.yul} | 12 ++--- .../EvmEmulatorFunctions.template.yul} | 0 .../EvmEmulatorLoop.template.yul} | 0 system-contracts/package.json | 2 +- system-contracts/scripts/deploy-preimages.ts | 54 +++++++++---------- .../scripts/preprocess-emulator.ts | 22 ++++++++ .../scripts/preprocess-interpreter.ts | 22 -------- 38 files changed, 149 insertions(+), 145 deletions(-) rename system-contracts/contracts/{EvmInterpreter.yul => EvmEmulator.yul} (99%) rename system-contracts/{evm-interpreter/EvmInterpreter.template.yul => evm-emulator/EvmEmulator.template.yul} (94%) rename system-contracts/{evm-interpreter/EvmInterpreterFunctions.template.yul => evm-emulator/EvmEmulatorFunctions.template.yul} (100%) rename system-contracts/{evm-interpreter/EvmInterpreterLoop.template.yul => evm-emulator/EvmEmulatorLoop.template.yul} (100%) create mode 100644 system-contracts/scripts/preprocess-emulator.ts delete mode 100644 system-contracts/scripts/preprocess-interpreter.ts diff --git a/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol b/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol index c1c3d2f4c..875e81715 100644 --- a/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol +++ b/l1-contracts/contracts/dev-contracts/test/CustomUpgradeTest.sol @@ -34,7 +34,7 @@ contract CustomUpgradeTest is BaseZkSyncUpgrade { _setBaseSystemContracts( _proposedUpgrade.bootloaderHash, _proposedUpgrade.defaultAccountHash, - _proposedUpgrade.evmSimulatorHash, + _proposedUpgrade.evmEmulatorHash, isPatchOnly ); diff --git a/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol b/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol index 1ff8fc2b6..5970e6be4 100644 --- a/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol +++ b/l1-contracts/contracts/dev-contracts/test/ExecutorProvingTest.sol @@ -32,15 +32,15 @@ contract ExecutorProvingTest is ExecutorFacet { return _processL2Logs(_newBatch, _expectedSystemContractUpgradeTxHash); } - /// Sets the DefaultAccount Hash and Bootloader Hash. + /// Sets the DefaultAccount Hash, Bootloader Hash and EVM emulator Hash. function setHashes( bytes32 l2DefaultAccountBytecodeHash, bytes32 l2BootloaderBytecodeHash, - bytes32 l2EvmSimulatorBytecode + bytes32 l2EvmEmulatorBytecode ) external { s.l2DefaultAccountBytecodeHash = l2DefaultAccountBytecodeHash; s.l2BootloaderBytecodeHash = l2BootloaderBytecodeHash; - s.l2EvmSimulatorBytecodeHash = l2EvmSimulatorBytecode; + s.l2EvmEmulatorBytecodeHash = l2EvmEmulatorBytecode; s.zkPorterIsAvailable = false; } } diff --git a/l1-contracts/contracts/state-transition/StateTransitionManager.sol b/l1-contracts/contracts/state-transition/StateTransitionManager.sol index cbb8706d6..a14298f2a 100644 --- a/l1-contracts/contracts/state-transition/StateTransitionManager.sol +++ b/l1-contracts/contracts/state-transition/StateTransitionManager.sol @@ -356,7 +356,7 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own factoryDeps: bytesEmptyArray, bootloaderHash: bytes32(0), defaultAccountHash: bytes32(0), - evmSimulatorHash: bytes32(0), + evmEmulatorHash: 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 531e3698a..48eabd4e1 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/DiamondInit.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/DiamondInit.sol @@ -62,7 +62,7 @@ contract DiamondInit is ZkSyncHyperchainBase, IDiamondInit { s.__DEPRECATED_verifierParams = _initializeData.verifierParams; s.l2BootloaderBytecodeHash = _initializeData.l2BootloaderBytecodeHash; s.l2DefaultAccountBytecodeHash = _initializeData.l2DefaultAccountBytecodeHash; - s.l2EvmSimulatorBytecodeHash = _initializeData.l2EvmSimulatorBytecodeHash; + s.l2EvmEmulatorBytecodeHash = _initializeData.l2EvmEmulatorBytecodeHash; 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 b490d2f62..952472e54 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol @@ -98,9 +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. + /// @notice Bytecode hash of evm emulator. /// @dev Used as an input to zkp-circuit. - bytes32 l2EvmSimulatorBytecodeHash; + bytes32 l2EvmEmulatorBytecodeHash; /// @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 c157a575d..bcef798f4 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol @@ -600,13 +600,13 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { function _batchMetaParameters() internal view returns (bytes memory) { bytes32 l2DefaultAccountBytecodeHash = s.l2DefaultAccountBytecodeHash; - bytes32 l2EvmSimulatorBytecodeHash = s.l2EvmSimulatorBytecodeHash; + bytes32 l2EvmEmulatorBytecodeHash = s.l2EvmEmulatorBytecodeHash; return abi.encodePacked( s.zkPorterIsAvailable, s.l2BootloaderBytecodeHash, l2DefaultAccountBytecodeHash, - l2EvmSimulatorBytecodeHash + l2EvmEmulatorBytecodeHash ); } 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 5ea7a92fa..5e7350edd 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol @@ -143,8 +143,8 @@ contract GettersFacet is ZkSyncHyperchainBase, IGetters, ILegacyGetters { } /// @inheritdoc IGetters - function getL2EvmSimulatorBytecodeHash() external view returns (bytes32) { - return s.l2EvmSimulatorBytecodeHash; + function getL2EvmEmulatorBytecodeHash() external view returns (bytes32) { + return s.l2EvmEmulatorBytecodeHash; } /// @inheritdoc IGetters diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IDiamondInit.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IDiamondInit.sol index ebc8686c6..893ff7b7b 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IDiamondInit.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IDiamondInit.sol @@ -18,6 +18,7 @@ import {FeeParams} from "../chain-deps/ZkSyncHyperchainStorage.sol"; /// @param verifierParams Verifier config parameters that describes the circuit to be verified /// @param l2BootloaderBytecodeHash The hash of bootloader L2 bytecode /// @param l2DefaultAccountBytecodeHash The hash of default account L2 bytecode +/// @param l2EvmEmulatorBytecodeHash The hash of EVM emulator L2 bytecode /// @param priorityTxMaxGasLimit maximum number of the L2 gas that a user can request for L1 -> L2 transactions /// @param feeParams Fee parameters to be used for L1->L2 transactions /// @param blobVersionedHashRetriever Address of contract used to pull the blob versioned hash for a transaction. @@ -36,7 +37,7 @@ struct InitializeData { VerifierParams verifierParams; bytes32 l2BootloaderBytecodeHash; bytes32 l2DefaultAccountBytecodeHash; - bytes32 l2EvmSimulatorBytecodeHash; + bytes32 l2EvmEmulatorBytecodeHash; uint256 priorityTxMaxGasLimit; FeeParams feeParams; address blobVersionedHashRetriever; @@ -46,6 +47,7 @@ struct InitializeData { /// @param verifierParams Verifier config parameters that describes the circuit to be verified /// @param l2BootloaderBytecodeHash The hash of bootloader L2 bytecode /// @param l2DefaultAccountBytecodeHash The hash of default account L2 bytecode +/// @param l2EvmEmulatorBytecodeHash The hash of EVM emulator L2 bytecode /// @param priorityTxMaxGasLimit maximum number of the L2 gas that a user can request for L1 -> L2 transactions /// @param feeParams Fee parameters to be used for L1->L2 transactions /// @param blobVersionedHashRetriever Address of contract used to pull the blob versioned hash for a transaction. @@ -54,7 +56,7 @@ struct InitializeDataNewChain { VerifierParams verifierParams; bytes32 l2BootloaderBytecodeHash; bytes32 l2DefaultAccountBytecodeHash; - bytes32 l2EvmSimulatorBytecodeHash; + bytes32 l2EvmEmulatorBytecodeHash; 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 dbcac8b57..d2e692978 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol @@ -81,8 +81,8 @@ 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 Bytecode hash of EVM emulator. + function getL2EvmEmulatorBytecodeHash() external view returns (bytes32); /// @return Verifier parameters. /// @dev This function is deprecated and will soon be removed. diff --git a/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol b/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol index b4c941989..c7f2453e3 100644 --- a/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol +++ b/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol @@ -35,7 +35,7 @@ struct ProposedUpgrade { bytes[] factoryDeps; bytes32 bootloaderHash; bytes32 defaultAccountHash; - bytes32 evmSimulatorHash; + bytes32 evmEmulatorHash; address verifier; VerifierParams verifierParams; bytes l1ContractsUpgradeCalldata; @@ -57,7 +57,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 Сhanges to the bytecode that is used in L2 as an EVM emulator + event NewL2EvmEmulatorBytecodeHash(bytes32 indexed previousBytecodeHash, bytes32 indexed newBytecodeHash); /// @notice Verifier address changed event NewVerifier(address indexed oldVerifier, address indexed newVerifier); @@ -87,7 +88,7 @@ abstract contract BaseZkSyncUpgrade is ZkSyncHyperchainBase { _setBaseSystemContracts( _proposedUpgrade.bootloaderHash, _proposedUpgrade.defaultAccountHash, - _proposedUpgrade.evmSimulatorHash, + _proposedUpgrade.evmEmulatorHash, isPatchOnly ); @@ -125,24 +126,24 @@ 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 + /// @notice Change EVM emulator bytecode hash, that is used on L2 + /// @param _l2EvmEmulatorBytecodeHash The hash of EVM emulator 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)) { + function _setL2EvmEmulatorBytecodeHash(bytes32 _l2EvmEmulatorBytecodeHash, bool _patchOnly) private { + if (_l2EvmEmulatorBytecodeHash == bytes32(0)) { return; } - require(!_patchOnly, "Patch only upgrade can not set new default account"); + require(!_patchOnly, "Patch only upgrade can not set new EVM emulator"); - L2ContractHelper.validateBytecodeHash(_l2EvmSimulatorBytecodeHash); + L2ContractHelper.validateBytecodeHash(_l2EvmEmulatorBytecodeHash); // Save previous value into the stack to put it into the event later - bytes32 previousL2EvmSimulatorBytecodeHash = s.l2EvmSimulatorBytecodeHash; + bytes32 previousL2EvmEmulatorBytecodeHash = s.l2EvmEmulatorBytecodeHash; // Change the default account bytecode hash - s.l2EvmSimulatorBytecodeHash = _l2EvmSimulatorBytecodeHash; - emit NewL2EvmSimulatorBytecodeHash(previousL2EvmSimulatorBytecodeHash, _l2EvmSimulatorBytecodeHash); + s.l2EvmEmulatorBytecodeHash = _l2EvmEmulatorBytecodeHash; + emit NewL2EvmEmulatorBytecodeHash(previousL2EvmEmulatorBytecodeHash, _l2EvmEmulatorBytecodeHash); } /// @notice Change bootloader bytecode hash, that is used on L2 @@ -214,16 +215,17 @@ abstract contract BaseZkSyncUpgrade is ZkSyncHyperchainBase { /// @notice Updates the bootloader hash and the hash of the default account /// @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 _evmEmulatorHash The hash of the new EVM emulator 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, + bytes32 _evmEmulatorHash, bool _patchOnly ) internal { _setL2BootloaderBytecodeHash(_bootloaderHash, _patchOnly); _setL2DefaultAccountBytecodeHash(_defaultAccountHash, _patchOnly); - _setL2EvmSimulatorBytecodeHash(_evmSimulatorHash, _patchOnly); + _setL2EvmEmulatorBytecodeHash(_evmEmulatorHash, _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 167abf40d..bca9c53ef 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -120,7 +120,7 @@ contract DeployL1Script is Script { bytes diamondCutData; bytes32 bootloaderHash; bytes32 defaultAAHash; - bytes32 evmSimulatorHash; + bytes32 evmEmulatorHash; } struct TokensConfig { @@ -443,7 +443,7 @@ contract DeployL1Script is Script { verifierParams: verifierParams, l2BootloaderBytecodeHash: config.contracts.bootloaderHash, l2DefaultAccountBytecodeHash: config.contracts.defaultAAHash, - l2EvmSimulatorBytecodeHash: config.contracts.evmSimulatorHash, + l2EvmEmulatorBytecodeHash: config.contracts.evmEmulatorHash, 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 49f444da4..96d19d43d 100644 --- a/l1-contracts/scripts/upgrade-consistency-checker.ts +++ b/l1-contracts/scripts/upgrade-consistency-checker.ts @@ -68,7 +68,7 @@ const expectedRecursionLeafLevelVkHash = "0xf9664f4324c1400fa5c3822d667f30e873f5 const expectedRecursionCircuitsSetVksHash = "0x0000000000000000000000000000000000000000000000000000000000000000"; const expectedBootloaderHash = "0x010008e7894d0dd14681c76bdb4d5e4e7f6b51bfe40c957d50eed3fec829fdb0"; const expectedDefaultAccountHash = "0x0100058deb36e1f2eeb48bf3846d0e8eb38e9176754b73116bb41a472459a4dd"; -const expectedEvmSimulatorHash = "0x01000f197081a9906cc411d0698c4961aeb5c74877f37f7071681da6e8ef3f31"; +const expectedEvmEmulatorHash = "0x01000f197081a9906cc411d0698c4961aeb5c74877f37f7071681da6e8ef3f31"; const validatorOne = process.env.ETH_SENDER_SENDER_OPERATOR_COMMIT_ETH_ADDR!; const validatorTwo = process.env.ETH_SENDER_SENDER_OPERATOR_BLOBS_ETH_ADDR!; @@ -222,7 +222,7 @@ async function extractProxyInitializationData(contract: ethers.Contract, data: s recursionCircuitsSetVksHash, l2BootloaderBytecodeHash, l2DefaultAccountBytecodeHash, - l2EvmSimulatorBytecodeHash, + l2EvmEmulatorBytecodeHash, // priorityTxMaxGasLimit, // // We unpack fee params @@ -279,8 +279,8 @@ 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"); + if (l2EvmEmulatorBytecodeHash.toLowerCase() !== expectedEvmEmulatorHash.toLowerCase()) { + throw new Error("L2 EVM emulator bytecode hash is not correct"); } console.log("STM init data correct!"); diff --git a/l1-contracts/scripts/utils.ts b/l1-contracts/scripts/utils.ts index e60434a8f..7903f708c 100644 --- a/l1-contracts/scripts/utils.ts +++ b/l1-contracts/scripts/utils.ts @@ -70,9 +70,9 @@ export function readSystemContractsBytecode(fileName: string) { return JSON.parse(artifact.toString()).bytecode; } -export function readEvmSimulatorbytecode() { +export function readEvmEmulatorbytecode() { 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/EvmEmulator.yul.zbin`); } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/l1-contracts/src.ts/deploy-process.ts b/l1-contracts/src.ts/deploy-process.ts index 42ab1329f..e9622bfbe 100644 --- a/l1-contracts/src.ts/deploy-process.ts +++ b/l1-contracts/src.ts/deploy-process.ts @@ -16,7 +16,7 @@ import { ADDRESS_ONE } from "../src.ts/utils"; export const L2_BOOTLOADER_BYTECODE_HASH = "0x1000100000000000000000000000000000000000000000000000000000000000"; export const L2_DEFAULT_ACCOUNT_BYTECODE_HASH = "0x1001000000000000000000000000000000000000000000000000000000000000"; -export const L2_EVM_SIMULATOR_BYTECODE_HASH = "0x1010000000000000000000000000000000000000000000000000000000000000"; +export const L2_EVM_EMULATOR_BYTECODE_HASH = "0x1010000000000000000000000000000000000000000000000000000000000000"; 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 09965b3d8..db37fc5e1 100644 --- a/l1-contracts/src.ts/deploy-test-process.ts +++ b/l1-contracts/src.ts/deploy-test-process.ts @@ -15,7 +15,7 @@ import { Deployer } from "./deploy"; import { L2_BOOTLOADER_BYTECODE_HASH, L2_DEFAULT_ACCOUNT_BYTECODE_HASH, - L2_EVM_SIMULATOR_BYTECODE_HASH, + L2_EVM_EMULATOR_BYTECODE_HASH, initialBridgehubDeployment, registerHyperchain, } from "./deploy-process"; @@ -66,7 +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, + evmEmulatorBytecodeHash: L2_EVM_EMULATOR_BYTECODE_HASH, }); } @@ -78,7 +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, + evmEmulatorBytecodeHash: L2_EVM_EMULATOR_BYTECODE_HASH, }); const l2_rpc_addr = "http://localhost:3050"; const web3Provider = new zkethers.Provider(l2_rpc_addr); @@ -318,7 +318,7 @@ export class EraDeployer extends Deployer { verifierParams, l2BootloaderBytecodeHash: L2_BOOTLOADER_BYTECODE_HASH, l2DefaultAccountBytecodeHash: L2_DEFAULT_ACCOUNT_BYTECODE_HASH, - l2EvmSimulatorBytecodeHash: L2_EVM_SIMULATOR_BYTECODE_HASH, + l2EvmEmulatorBytecodeHash: L2_EVM_EMULATOR_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 889a699a9..0075b676c 100644 --- a/l1-contracts/src.ts/deploy.ts +++ b/l1-contracts/src.ts/deploy.ts @@ -10,7 +10,7 @@ import { packSemver, readBatchBootloaderBytecode, readSystemContractsBytecode, - readEvmSimulatorbytecode, + readEvmEmulatorbytecode, unpackStringSemVer, } from "../scripts/utils"; import { getTokens } from "./deploy-token"; @@ -44,7 +44,7 @@ import type { Contract, Overrides } from "@ethersproject/contracts"; let L2_BOOTLOADER_BYTECODE_HASH: string; let L2_DEFAULT_ACCOUNT_BYTECODE_HASH: string; -let L2_EVM_SIMULATOR_BYTECODE_HASH: string; +let L2_EVM_EMULATOR_BYTECODE_HASH: string; export interface DeployerConfig { deployWallet: Wallet; @@ -53,7 +53,7 @@ export interface DeployerConfig { verbose?: boolean; bootloaderBytecodeHash?: string; defaultAccountBytecodeHash?: string; - evmSimulatorBytecodeHash?: string; + evmEmulatorBytecodeHash?: string; } export interface Operation { @@ -81,9 +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())); + L2_EVM_EMULATOR_BYTECODE_HASH = config.evmEmulatorBytecodeHash + ? config.evmEmulatorBytecodeHash + : hexlify(hashL2Bytecode(readEvmEmulatorbytecode())); this.ownerAddress = config.ownerAddress != null ? config.ownerAddress : this.deployWallet.address; this.chainId = parseInt(process.env.CHAIN_ETH_ZKSYNC_NETWORK_ID!); } @@ -111,7 +111,7 @@ export class Deployer { verifierParams, L2_BOOTLOADER_BYTECODE_HASH, L2_DEFAULT_ACCOUNT_BYTECODE_HASH, - L2_EVM_SIMULATOR_BYTECODE_HASH, + L2_EVM_EMULATOR_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 99759fa46..0bc960fc0 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; + l2EvmEmulatorBytecodeHash: string; priorityTxMaxGasLimit: BigNumberish; } diff --git a/l1-contracts/src.ts/utils.ts b/l1-contracts/src.ts/utils.ts index 5955f0497..41bca767b 100644 --- a/l1-contracts/src.ts/utils.ts +++ b/l1-contracts/src.ts/utils.ts @@ -136,7 +136,7 @@ export interface ProposedUpgrade { factoryDeps: BytesLike[]; bootloaderHash: BytesLike; defaultAccountHash: BytesLike; - evmSimulatorHash: BytesLike; + evmEmulatorHash: BytesLike; verifier: string; verifierParams: VerifierParams; l1ContractsUpgradeCalldata: BytesLike; @@ -188,7 +188,7 @@ function checkValidInitialCutHashParams( verifierParams: VerifierParams, l2BootloaderBytecodeHash: string, l2DefaultAccountBytecodeHash: string, - l2EvmSimulatorBytecodeHash: string, + l2EvmEmulatorBytecodeHash: string, verifier: string, blobVersionedHashRetriever: string, priorityTxMaxGasLimit: number @@ -217,8 +217,8 @@ 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 (l2EvmEmulatorBytecodeHash === ethers.constants.HashZero) { + throw new Error("L2 evm emulator bytecode hash is zero"); } if (verifier === ethers.constants.AddressZero) { throw new Error("Verifier address is zero"); @@ -239,7 +239,7 @@ export function compileInitialCutHash( verifierParams: VerifierParams, l2BootloaderBytecodeHash: string, l2DefaultAccountBytecodeHash: string, - l2EvmSimulatorBytecodeHash: string, + l2EvmEmulatorBytecodeHash: string, verifier: string, blobVersionedHashRetriever: string, priorityTxMaxGasLimit: number, @@ -252,7 +252,7 @@ export function compileInitialCutHash( verifierParams, l2BootloaderBytecodeHash, l2DefaultAccountBytecodeHash, - l2EvmSimulatorBytecodeHash, + l2EvmEmulatorBytecodeHash, verifier, blobVersionedHashRetriever, priorityTxMaxGasLimit @@ -286,7 +286,7 @@ export function compileInitialCutHash( verifierParams, l2BootloaderBytecodeHash, l2DefaultAccountBytecodeHash, - l2EvmSimulatorBytecodeHash, + l2EvmEmulatorBytecodeHash, 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 1ee6bcebd..5025af8a5 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, - l2EvmSimulatorBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, + l2EvmEmulatorBytecodeHash: 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 36cc60ac9..fcf039155 100644 --- a/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Executor/ExecutorProof.t.sol @@ -77,7 +77,7 @@ contract ExecutorProofTest is Test { utilsFacet.util_setL2DefaultAccountBytecodeHash( 0x0100058d1abd41a9984b37939862f99c18237dc6951c3d5a3d81593c798a8f81 ); - utilsFacet.util_setL2EvmSimulatorBytecodeHash( + utilsFacet.util_setL2EvmEmulatorBytecodeHash( 0x01000f196acd122635a752fcb275be0cc95fd3bba348c1d0908a517fe316418e ); utilsFacet.util_setL2BootloaderBytecodeHash(0x010008ddde4acc465cde1c420883701caadb41954567c0b4e3a0d1093a7afde7); 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 18fb220e4..e9a63985a 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,7 +83,7 @@ contract ExecutorTest is Test { selectors[12] = getters.storedBatchHash.selector; selectors[13] = getters.getL2BootloaderBytecodeHash.selector; selectors[14] = getters.getL2DefaultAccountBytecodeHash.selector; - selectors[15] = getters.getL2EvmSimulatorBytecodeHash.selector; + selectors[15] = getters.getL2EvmEmulatorBytecodeHash.selector; selectors[16] = getters.getVerifierParams.selector; selectors[17] = getters.isDiamondStorageFrozen.selector; selectors[18] = getters.getPriorityTxMaxGasLimit.selector; @@ -178,7 +178,7 @@ contract ExecutorTest is Test { }), l2BootloaderBytecodeHash: dummyHash, l2DefaultAccountBytecodeHash: dummyHash, - l2EvmSimulatorBytecodeHash: dummyHash, + l2EvmEmulatorBytecodeHash: 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 008a93db4..915264aa9 100644 --- a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol +++ b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol @@ -226,7 +226,7 @@ library Utils { selectors[12] = GettersFacet.storedBatchHash.selector; selectors[13] = GettersFacet.getL2BootloaderBytecodeHash.selector; selectors[14] = GettersFacet.getL2DefaultAccountBytecodeHash.selector; - selectors[15] = GettersFacet.getL2EvmSimulatorBytecodeHash.selector; + selectors[15] = GettersFacet.getL2EvmEmulatorBytecodeHash.selector; selectors[16] = GettersFacet.getVerifierParams.selector; selectors[17] = GettersFacet.isDiamondStorageFrozen.selector; selectors[18] = GettersFacet.getPriorityTxMaxGasLimit.selector; @@ -278,8 +278,8 @@ library Utils { selectors[15] = UtilsFacet.util_getL2BootloaderBytecodeHash.selector; selectors[16] = UtilsFacet.util_setL2DefaultAccountBytecodeHash.selector; selectors[17] = UtilsFacet.util_getL2DefaultAccountBytecodeHash.selector; - selectors[18] = UtilsFacet.util_getL2EvmSimulatorBytecodeHash.selector; - selectors[19] = UtilsFacet.util_setL2EvmSimulatorBytecodeHash.selector; + selectors[18] = UtilsFacet.util_getL2EvmEmulatorBytecodeHash.selector; + selectors[19] = UtilsFacet.util_setL2EvmEmulatorBytecodeHash.selector; selectors[20] = UtilsFacet.util_setPendingAdmin.selector; selectors[21] = UtilsFacet.util_getPendingAdmin.selector; selectors[22] = UtilsFacet.util_setAdmin.selector; @@ -343,7 +343,7 @@ library Utils { verifierParams: makeVerifierParams(), l2BootloaderBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, l2DefaultAccountBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, - l2EvmSimulatorBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, + l2EvmEmulatorBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, priorityTxMaxGasLimit: 500000, feeParams: makeFeeParams(), blobVersionedHashRetriever: address(0x23746765237749923040872834) @@ -359,7 +359,7 @@ library Utils { verifierParams: makeVerifierParams(), l2BootloaderBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, l2DefaultAccountBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, - l2EvmSimulatorBytecodeHash: 0x0100000000000000000000000000000000000000000000000000000000000000, + l2EvmEmulatorBytecodeHash: 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 55c696b8e..25a2be4fb 100644 --- a/l1-contracts/test/foundry/unit/concrete/Utils/UtilsFacet.sol +++ b/l1-contracts/test/foundry/unit/concrete/Utils/UtilsFacet.sol @@ -80,12 +80,12 @@ contract UtilsFacet is ZkSyncHyperchainBase { return s.l2DefaultAccountBytecodeHash; } - function util_setL2EvmSimulatorBytecodeHash(bytes32 _l2EvmSimulatorBytecodeHash) external { - s.l2EvmSimulatorBytecodeHash = _l2EvmSimulatorBytecodeHash; + function util_setL2EvmEmulatorBytecodeHash(bytes32 _l2EvmEmulatorBytecodeHash) external { + s.l2EvmEmulatorBytecodeHash = _l2EvmEmulatorBytecodeHash; } - function util_getL2EvmSimulatorBytecodeHash() external view returns (bytes32) { - return s.l2EvmSimulatorBytecodeHash; + function util_getL2EvmEmulatorBytecodeHash() external view returns (bytes32) { + return s.l2EvmEmulatorBytecodeHash; } function util_setPendingAdmin(address _pendingAdmin) external { 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 cac368a2b..9433175cf 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_getL2EvmEmulatorBytecodeHash(), initializeData.l2EvmEmulatorBytecodeHash); 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/Admin/ExecuteUpgrade.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Admin/ExecuteUpgrade.t.sol index 71ccfc581..edf687dd4 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,7 +45,7 @@ contract ExecuteUpgradeTest is AdminTest { factoryDeps: new bytes[](0), bootloaderHash: bytes32(0), defaultAccountHash: bytes32(0), - evmSimulatorHash: bytes32(0), + evmEmulatorHash: bytes32(0), verifier: address(0), verifierParams: verifierParams, l1ContractsUpgradeCalldata: hex"", 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 948c79925..5bf4d7639 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,8 +90,8 @@ contract GettersFacetWrapper is GettersFacet { s.l2DefaultAccountBytecodeHash = _l2DefaultAccountBytecodeHash; } - function utils_setL2EvmSimulatorBytecodeHash(bytes32 _l2EvmSimulatorBytecodeHash) external { - s.l2EvmSimulatorBytecodeHash = _l2EvmSimulatorBytecodeHash; + function utils_setL2EvmEmulatorBytecodeHash(bytes32 _l2EvmEmulatorBytecodeHash) external { + s.l2EvmEmulatorBytecodeHash = _l2EvmEmulatorBytecodeHash; } function util_setVerifierParams(VerifierParams memory _verifierParams) external { diff --git a/l1-contracts/test/unit_tests/executor_proof.spec.ts b/l1-contracts/test/unit_tests/executor_proof.spec.ts index 8bbb46df3..d99b7c197 100644 --- a/l1-contracts/test/unit_tests/executor_proof.spec.ts +++ b/l1-contracts/test/unit_tests/executor_proof.spec.ts @@ -17,9 +17,9 @@ describe("Executor test", function () { it("Test hashes (Rollup)", async () => { const bootloaderHash = "0x010008bbde6fc402ea3a3d6cb15cb97e70245d3d4e48fb74362d4961b74c16b1"; const aaHash = "0x0100058d9eee51f4b9e9a9ecb7fd7e8301e90bef018c2bd913ed36e583fec8c2"; - const evmSimulatorHash = "0x01000ccb740e2345754450eda583f59b31a346920a22f968dfcfc63feae303ee"; + const evmEmulatorHash = "0x01000ccb740e2345754450eda583f59b31a346920a22f968dfcfc63feae303ee"; - const setResult = await executor.setHashes(aaHash, bootloaderHash, evmSimulatorHash); + const setResult = await executor.setHashes(aaHash, bootloaderHash, evmEmulatorHash); const finish = await setResult.wait(); expect(finish.status == 1); 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 96d00a531..41fe17544 100644 --- a/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts +++ b/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts @@ -416,7 +416,7 @@ describe.only("L2 upgrade test", function () { it("Should successfully perform an upgrade", async () => { const bootloaderHash = ethers.utils.hexlify(hashBytecode(ethers.utils.randomBytes(32))); const defaultAccountHash = ethers.utils.hexlify(hashBytecode(ethers.utils.randomBytes(32))); - const evmSimulatorHash = ethers.utils.hexlify(hashBytecode(ethers.utils.randomBytes(32))); + const evmEmulatorHash = ethers.utils.hexlify(hashBytecode(ethers.utils.randomBytes(32))); const testnetVerifierFactory = await hardhat.ethers.getContractFactory("TestnetVerifier"); const testnetVerifierContract = await testnetVerifierFactory.deploy(); const newVerifier = testnetVerifierContract.address; @@ -436,7 +436,7 @@ describe.only("L2 upgrade test", function () { const upgrade = { bootloaderHash, defaultAccountHash, - evmSimulatorHash, + evmEmulatorHash, verifier: newVerifier, verifierParams: newerVerifierParams, executeUpgradeTx: true, @@ -468,7 +468,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); - expect(await proxyGetters.getL2EvmSimulatorBytecodeHash()).to.equal(evmSimulatorHash); + expect(await proxyGetters.getL2EvmEmulatorBytecodeHash()).to.equal(evmEmulatorHash); expect((await proxyGetters.getVerifier()).toLowerCase()).to.equal(newVerifier.toLowerCase()); expect(await proxyGetters.getProtocolVersion()).to.equal(addToProtocolVersion(initialProtocolVersion, 5, 0)); @@ -512,7 +512,7 @@ describe.only("L2 upgrade test", function () { const currentVerifierParams = await proxyGetters.getVerifierParams(); const currentBootloaderHash = await proxyGetters.getL2BootloaderBytecodeHash(); const currentL2DefaultAccountBytecodeHash = await proxyGetters.getL2DefaultAccountBytecodeHash(); - const currentL2EvmSimulatorBytecodeHash = await proxyGetters.getL2EvmSimulatorBytecodeHash(); + const currentL2EvmEmulatorBytecodeHash = await proxyGetters.getL2EvmEmulatorBytecodeHash(); const testnetVerifierFactory = await hardhat.ethers.getContractFactory("TestnetVerifier"); const testnetVerifierContract = await testnetVerifierFactory.deploy(); @@ -557,7 +557,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); - expect(await proxyGetters.getL2EvmSimulatorBytecodeHash()).to.equal(currentL2EvmSimulatorBytecodeHash); + expect(await proxyGetters.getL2EvmEmulatorBytecodeHash()).to.equal(currentL2EvmEmulatorBytecodeHash); expect((await proxyGetters.getVerifier()).toLowerCase()).to.equal(newVerifier.toLowerCase()); expect(await proxyGetters.getProtocolVersion()).to.equal(addToProtocolVersion(initialProtocolVersion, 5, 1)); @@ -948,7 +948,7 @@ function buildProposeUpgrade(proposedUpgrade: PartialProposedUpgrade): ProposedU l2ProtocolUpgradeTx: buildL2CanonicalTransaction({ nonce: newProtocolVersion }), bootloaderHash: ethers.constants.HashZero, defaultAccountHash: ethers.constants.HashZero, - evmSimulatorHash: ethers.constants.HashZero, + evmEmulatorHash: ethers.constants.HashZero, verifier: ethers.constants.AddressZero, verifierParams: buildVerifierParams({}), l1ContractsUpgradeCalldata: "0x", diff --git a/l1-contracts/test/unit_tests/proxy_test.spec.ts b/l1-contracts/test/unit_tests/proxy_test.spec.ts index 712bde127..4f6dc204a 100644 --- a/l1-contracts/test/unit_tests/proxy_test.spec.ts +++ b/l1-contracts/test/unit_tests/proxy_test.spec.ts @@ -96,7 +96,7 @@ describe("Diamond proxy tests", function () { verifierParams: dummyVerifierParams, l2BootloaderBytecodeHash: "0x0100000000000000000000000000000000000000000000000000000000000000", l2DefaultAccountBytecodeHash: "0x0100000000000000000000000000000000000000000000000000000000000000", - l2EvmSimulatorBytecodeHash: "0x0100000000000000000000000000000000000000000000000000000000000000", + l2EvmEmulatorBytecodeHash: "0x0100000000000000000000000000000000000000000000000000000000000000", priorityTxMaxGasLimit: 500000, // priority tx max L2 gas limit feeParams: defaultFeeParams(), blobVersionedHashRetriever: "0x0000000000000000000000000000000000000001", diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 2f0d9d00f..a2a5c8ca2 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -126,9 +126,9 @@ "sourceCodeHash": "0xfcf4828bcc109dea5f88c38f428d9ac5e18d5a2767fa4909277802c7e38c1f93" }, { - "contractName": "EvmInterpreter", - "bytecodePath": "contracts-preprocessed/artifacts/EvmInterpreter.yul.zbin", - "sourceCodePath": "contracts-preprocessed/EvmInterpreter.yul", + "contractName": "EvmEmulator", + "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul.zbin", + "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", "bytecodeHash": "0x01000cdf5bb7dd8a97faf231a5e1e20f2fe308d6f200c3295c6e3629547cc4a4", "sourceCodeHash": "0xe1133c2af9e4fc38e845f7fcc23f3cbab37b857013f55b6e7e9bdea28f331c40" }, diff --git a/system-contracts/contracts/EvmInterpreter.yul b/system-contracts/contracts/EvmEmulator.yul similarity index 99% rename from system-contracts/contracts/EvmInterpreter.yul rename to system-contracts/contracts/EvmEmulator.yul index 1833f2c25..c9548e1a1 100644 --- a/system-contracts/contracts/EvmInterpreter.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1,4 +1,4 @@ -object "EVMInterpreter" { +object "EvmEmulator" { 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 @@ -2912,7 +2912,7 @@ object "EVMInterpreter" { setDeployedCode(gasToReturn, offset, len) } - object "EVMInterpreter_deployed" { + object "EvmEmulator_deployed" { code { function ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008002 diff --git a/system-contracts/evm-interpreter/EvmInterpreter.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul similarity index 94% rename from system-contracts/evm-interpreter/EvmInterpreter.template.yul rename to system-contracts/evm-emulator/EvmEmulator.template.yul index 0aed3e039..88842853e 100644 --- a/system-contracts/evm-interpreter/EvmInterpreter.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -1,4 +1,4 @@ -object "EVMInterpreter" { +object "EvmEmulator" { 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 @@ -80,7 +80,7 @@ object "EVMInterpreter" { returnGas := chargeGas(gasToReturn, gasForCode) } - + function simulate( isCallerEVM, @@ -91,7 +91,7 @@ object "EVMInterpreter" { returnOffset := MEM_OFFSET_INNER() returnLen := 0 - + retGasLeft := evmGasLeft } @@ -120,9 +120,9 @@ object "EVMInterpreter" { setDeployedCode(gasToReturn, offset, len) } - object "EVMInterpreter_deployed" { + object "EvmEmulator_deployed" { code { - + function $llvm_NoInline_llvm$_simulate( isCallerEVM, @@ -133,7 +133,7 @@ object "EVMInterpreter" { returnOffset := MEM_OFFSET_INNER() returnLen := 0 - + if eq(isCallerEVM, 1) { // Includes gas diff --git a/system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul similarity index 100% rename from system-contracts/evm-interpreter/EvmInterpreterFunctions.template.yul rename to system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul diff --git a/system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul similarity index 100% rename from system-contracts/evm-interpreter/EvmInterpreterLoop.template.yul rename to system-contracts/evm-emulator/EvmEmulatorLoop.template.yul diff --git a/system-contracts/package.json b/system-contracts/package.json index 1a04c8632..e4b97d4ee 100644 --- a/system-contracts/package.json +++ b/system-contracts/package.json @@ -63,7 +63,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:emulator": "rm -f ./contracts/EvmEmulator.yul && yarn ts-node scripts/preprocess-emulator.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/deploy-preimages.ts b/system-contracts/scripts/deploy-preimages.ts index afff747cb..b13917a0e 100644 --- a/system-contracts/scripts/deploy-preimages.ts +++ b/system-contracts/scripts/deploy-preimages.ts @@ -23,7 +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 EVM_EMULATOR_CONTRACT_NAME = "EvmEmulator"; const CONSOLE_COLOR_RESET = "\x1b[0m"; const CONSOLE_COLOR_RED = "\x1b[31m"; @@ -158,51 +158,51 @@ class ZkSyncDeployer { return await zkSync.getL2BootloaderBytecodeHash(); } - // Returns the current default evm simulator bytecode on zkSync - async currentEvmSimulatorBytecode(): Promise { + // Returns the current evm emulator bytecode on zkSync + async currentEvmEmulatorBytecode(): Promise { const zkSync = await this.deployer.zkWallet.getMainContract(); - return await zkSync.getL2EvmSimulatorBytecodeHash(); + return await zkSync.getL2EvmEmulatorBytecodeHash(); } - // 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 needed, appends the evm emulator bytecode to the upgrade + async checkShouldUpgradeEvmEmulator(evmEmulatorBytecode: string) { + const bytecodeHash = ethers.utils.hexlify(hashBytecode(evmEmulatorBytecode)); + const currentEvmEmulatorBytecode = ethers.utils.hexlify(await this.currentEvmEmulatorBytecode()); // 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) { + if (bytecodeHash.toLowerCase() !== currentEvmEmulatorBytecode) { this.defaultAccountToUpgrade = { - name: EVM_SIMULATOR_CONTRACT_NAME, + name: EVM_EMULATOR_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; + // Publishes the bytecode of the evm emulator and appends it to the deployed bytecodes if needed. + async processEvmEmulator() { + const defaultEvmEmulator = (await this.deployer.loadArtifact(EVM_EMULATOR_CONTRACT_NAME)).bytecode; - await this.publishEvmSimulator(defaultEvmSimulator); - await this.checkShouldUpgradeEvmSimulator(defaultEvmSimulator); + await this.publishEvmEmulator(defaultEvmEmulator); + await this.checkShouldUpgradeEvmEmulator(defaultEvmEmulator); } - async publishEvmSimulator(defaultEvmSimulatorBytecode: string) { - const [defaultEvmSimulatorBytecodes] = await filterPublishedFactoryDeps( - EVM_SIMULATOR_CONTRACT_NAME, - [defaultEvmSimulatorBytecode], + async publishEvmEmulator(defaultEvmEmulatorBytecode: string) { + const [defaultEvmEmulatorBytecodes] = await filterPublishedFactoryDeps( + EVM_EMULATOR_CONTRACT_NAME, + [defaultEvmEmulatorBytecode], this.deployer ); - if (defaultEvmSimulatorBytecodes.length == 0) { - console.log("Default evm simulator is already published, skipping"); + if (defaultEvmEmulatorBytecodes.length == 0) { + console.log("Default evm emulator is already published, skipping"); return; } - // Publish evm simulator bytecode + // Publish evm emulator bytecode await this.publishFactoryDeps([ { - name: EVM_SIMULATOR_CONTRACT_NAME, - bytecodes: defaultEvmSimulatorBytecodes, + name: EVM_EMULATOR_CONTRACT_NAME, + bytecodes: defaultEvmEmulatorBytecodes, }, ]); } @@ -352,7 +352,7 @@ async function main() { .option("--l2Rpc ") .option("--bootloader") .option("--default-aa") - .option("--evm-simulator") + .option("--evm-emulator") .option("--system-contracts") .option("--file ") .action(async (cmd) => { @@ -391,8 +391,8 @@ async function main() { await zkSyncDeployer.processDefaultAA(); } - if (cmd.evmSimulator) { - await zkSyncDeployer.processEvmSimulator(); + if (cmd.evmEmulator) { + await zkSyncDeployer.processEvmEmulator(); } if (cmd.systemContracts) { diff --git a/system-contracts/scripts/preprocess-emulator.ts b/system-contracts/scripts/preprocess-emulator.ts new file mode 100644 index 000000000..5f49df926 --- /dev/null +++ b/system-contracts/scripts/preprocess-emulator.ts @@ -0,0 +1,22 @@ +import { 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"; +const INPUT_DIR = "evm-emulator"; + +async function main() { + process.chdir(`${INPUT_DIR}`); + const emulatorSource = readFileSync("EvmEmulator.template.yul").toString(); + + console.log("Preprocessing Emulator"); + const emulator = preprocess.preprocess(emulatorSource); + + writeFileSync(`../${OUTPUT_DIR}/EvmEmulator.yul`, emulator); + + console.log("Emulator preprocessing done!"); +} + +main(); diff --git a/system-contracts/scripts/preprocess-interpreter.ts b/system-contracts/scripts/preprocess-interpreter.ts deleted file mode 100644 index 2b031ab9c..000000000 --- a/system-contracts/scripts/preprocess-interpreter.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { 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"; -const INPUT_DIR = "evm-interpreter"; - -async function main() { - process.chdir(`${INPUT_DIR}`); - const interpreterSource = readFileSync("EvmInterpreter.template.yul").toString(); - - console.log("Preprocessing Interpreter"); - const interpreter = preprocess.preprocess(interpreterSource); - - writeFileSync(`../${OUTPUT_DIR}/EvmInterpreter.yul`, interpreter); - - console.log("Interpreter preprocessing done!"); -} - -main(); From 1e375d14e0d17acb6db353184fe0a34bf0e30295 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 14 Oct 2024 14:51:25 +0300 Subject: [PATCH 071/183] fix(EVM): Fix accessed accounts behavior according to EVM (#865) --- system-contracts/contracts/EvmEmulator.yul | 8 ++------ system-contracts/contracts/EvmGasManager.sol | 20 +++++++++++++++---- .../evm-emulator/EvmEmulator.template.yul | 4 ++-- .../EvmEmulatorFunctions.template.yul | 2 -- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index c9548e1a1..b13e6447c 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1180,8 +1180,6 @@ object "EvmEmulator" { } 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()) @@ -2892,6 +2890,8 @@ object "EvmEmulator" { // FALLBACK //////////////////////////////////////////////////////////////// + pop($llvm_AlwaysInline_llvm$_warmAddress(address())) + let evmGasLeft, isStatic, isCallerEVM := consumeEvmFrame() if isStatic { @@ -4014,8 +4014,6 @@ object "EvmEmulator" { } 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()) @@ -5744,8 +5742,6 @@ object "EvmEmulator" { // 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/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index 30bc9f938..556852160 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -50,7 +50,7 @@ contract EvmGasManager { // This error should never happen revert(0, 0) } - + rawCodeHash := mload(0) } @@ -146,17 +146,29 @@ contract EvmGasManager { } function consumeEvmFrame() external payable onlySystemEvm returns (uint256 passGas, uint256 auxDataRes) { + bool isFrameActive; + bytes32 auxData; assembly { - let auxData := tload(EVM_AUX_DATA_SLOT) - let isFrameActive := and(auxData, EVM_ACTIVE_FRAME_FLAG) + auxData := tload(EVM_AUX_DATA_SLOT) + isFrameActive := and(auxData, EVM_ACTIVE_FRAME_FLAG) + } - if isFrameActive { + if (isFrameActive) { + assembly { passGas := tload(EVM_GAS_SLOT) auxDataRes := auxData tstore(EVM_AUX_DATA_SLOT, 0) // mark as consumed } + } else { + // add sender to the warm accounts + uint256 is_sender_warm_tslot = IS_ACCOUNT_WARM_PREFIX | uint256(uint160(msg.sender)); + assembly { + tstore(is_sender_warm_tslot, 1) + } + } + assembly { mstore(0x0, passGas) mstore(0x20, auxDataRes) return(0x0, 0x40) diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index 88842853e..2ac84f0c0 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -100,6 +100,8 @@ object "EvmEmulator" { // FALLBACK //////////////////////////////////////////////////////////////// + pop($llvm_AlwaysInline_llvm$_warmAddress(address())) + let evmGasLeft, isStatic, isCallerEVM := consumeEvmFrame() if isStatic { @@ -160,8 +162,6 @@ object "EvmEmulator" { // 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/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 1e4ec38f7..032a83e8d 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -1098,8 +1098,6 @@ function _fetchConstructorReturnGas() -> gasLeft { } 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()) From bf7f9551fd199922808b61df3b2714306758de6b Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 18 Oct 2024 09:33:43 +0200 Subject: [PATCH 072/183] feat: Update zksolc for system contracts (#830) --- .github/workflows/system-contracts-ci.yaml | 2 +- l1-contracts/deploy-scripts/Utils.sol | 2 +- l1-contracts/scripts/utils.ts | 7 +- system-contracts/SystemContractsHashes.json | 88 +- .../bootloader/test_infra/Cargo.lock | 3832 ++++++++++------- .../bootloader/test_infra/Cargo.toml | 12 +- .../bootloader/test_infra/rust-toolchain | 2 +- .../bootloader/test_infra/src/hook.rs | 6 +- .../bootloader/test_infra/src/main.rs | 53 +- .../test_infra/src/test_count_tracer.rs | 8 +- .../bootloader/test_infra/src/tracer.rs | 13 +- .../test-contracts/ExtraAbiCaller.zasm | 54 +- system-contracts/foundry.toml | 2 +- system-contracts/hardhat.config.ts | 9 +- system-contracts/package.json | 2 +- system-contracts/scripts/calculate-hashes.ts | 4 +- system-contracts/scripts/compile-yul.ts | 15 +- system-contracts/scripts/compile-zasm.ts | 4 +- system-contracts/scripts/deploy-preimages.ts | 11 +- system-contracts/scripts/utils.ts | 12 +- yarn.lock | 113 +- 21 files changed, 2545 insertions(+), 1706 deletions(-) diff --git a/.github/workflows/system-contracts-ci.yaml b/.github/workflows/system-contracts-ci.yaml index f842214d6..98d005a35 100644 --- a/.github/workflows/system-contracts-ci.yaml +++ b/.github/workflows/system-contracts-ci.yaml @@ -64,7 +64,7 @@ jobs: - name: Install rust uses: actions-rust-lang/setup-rust-toolchain@v1 with: - toolchain: nightly-2023-04-17 + toolchain: nightly-2024-08-01 - name: Restore artifacts cache uses: actions/cache/restore@v3 diff --git a/l1-contracts/deploy-scripts/Utils.sol b/l1-contracts/deploy-scripts/Utils.sol index 440eadcac..ad8c96094 100644 --- a/l1-contracts/deploy-scripts/Utils.sol +++ b/l1-contracts/deploy-scripts/Utils.sol @@ -109,7 +109,7 @@ library Utils { * @dev Returns the bytecode hash of the batch bootloader. */ function getBatchBootloaderBytecodeHash() internal view returns (bytes memory) { - return vm.readFileBinary("../system-contracts/bootloader/build/artifacts/proved_batch.yul.zbin"); + return vm.readFile("../system-contracts/bootloader/build/artifacts/proved_batch.yul/proved_batch.yul.zbin"); } /** diff --git a/l1-contracts/scripts/utils.ts b/l1-contracts/scripts/utils.ts index 5ae1bceac..48b9c1760 100644 --- a/l1-contracts/scripts/utils.ts +++ b/l1-contracts/scripts/utils.ts @@ -59,7 +59,12 @@ export function web3Provider() { export function readBatchBootloaderBytecode() { const bootloaderPath = path.join(process.env.ZKSYNC_HOME as string, "contracts/system-contracts/bootloader"); - return fs.readFileSync(`${bootloaderPath}/build/artifacts/proved_batch.yul.zbin`); + + return readBytecodeUtf8(`${bootloaderPath}/build/artifacts/proved_batch.yul/proved_batch.yul.zbin`); +} + +export function readBytecodeUtf8(path: string) { + return ethers.utils.hexlify(fs.readFileSync(path).toString(), { allowMissingPrefix: true }); } export function readSystemContractsBytecode(fileName: string) { diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 18da55393..8eeff8ac5 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,210 +3,210 @@ "contractName": "AccountCodeStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x0100005d05a277543946914759aa4a6c403604b828f80d00b900c669c3d224e1", + "bytecodeHash": "0x01000059c988dac86a1fe9ff2d929f118eaf640d2c073a7e089f33cda3183784", "sourceCodeHash": "0x2e0e09d57a04bd1e722d8bf8c6423fdf3f8bca44e5e8c4f6684f987794be066e" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010007c7bb63f64649098bf75f4baa588db20f445b4d20b7cca972d5d8f973ce", + "bytecodeHash": "0x010006dfcc723139e24b127181ad5cec6c4b57935c944548ad2e7b65505bdedd", "sourceCodeHash": "0x0f1213c4b95acb71f4ab5d4082cc1aeb2bd5017e1cccd46afc66e53268609d85" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004da9f3aa5e4febcc53522cb7ee6949369fde25dd79e977752b82b9fd5d", + "bytecodeHash": "0x01000047171b9f2496e91fedc2a691b926d67c664718e09e7741abb936356ce8", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100014fb4f05ae09288cbcf4fa7a09ca456910f6e69be5ac2c2dfc8d71d1576", + "bytecodeHash": "0x0100013f5629aea4f024a0391184de582368e27eb00fd4e4f04d38285127e04f", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010004e5d52d692822d5c54ac87de3297f39be0e4a6f72f2830ae5ac856684ee", + "bytecodeHash": "0x0100042db9e3c6a96189306802a818ad22ceac9beb9750d184a17be348efc5b9", "sourceCodeHash": "0x82f81fbf5fb007a9cac97462d50907ca5d7a1af62d82d2645e093ed8647a5209" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x010000495bd172e90725e6bfafe73e36a288d616d4673f5347eeb819a78bf546", + "bytecodeHash": "0x0100003f67bf604cec81253c6d5876dfc05255da12ad83ee32f56a2e3233fb8f", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100055dba11508480be023137563caec69debc85f826cb3a4b68246a7cabe30", + "bytecodeHash": "0x010004dbb7b5d17f1013d67de0409a8fa3bc84af9226b5c759b9a0a1d0a2e8dc", "sourceCodeHash": "0xebffe840ebbd9329edb1ebff8ca50f6935e7dabcc67194a896fcc2e968d46dfb" }, { "contractName": "EmptyContract", "bytecodePath": "artifacts-zk/contracts-preprocessed/EmptyContract.sol/EmptyContract.json", "sourceCodePath": "contracts-preprocessed/EmptyContract.sol", - "bytecodeHash": "0x010000078f32964c38fbd138a0369f4723f07ac6f4919c45ef738c18bf874ccd", + "bytecodeHash": "0x01000007947dfd1aab45b52e5998b442bfbd4d565af494fb8082a810c6ed0b50", "sourceCodeHash": "0xcac36c5afafbcff83601f4fbfdff660aa66d8c80ed97b9322d3011c1926b554d" }, { "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000039785a8e0d342a49b6b6c6e156801b816434d93bee85d33f56d56b4f9a", + "bytecodeHash": "0x01000033962f4c689f265e804df8ae9ab06f1ab8d044e72385e41bcd411d04a2", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x0100006f0f209c9e6d06b1327db1257b15fa7a8b9864ee5ccd12cd3f8bc40ac9", + "bytecodeHash": "0x0100006916feb836433c433d6e82f97fb159fe1feb3dd2523de09b23a2335a79", "sourceCodeHash": "0xb39b5b81168653e0c5062f7b8e1d6d15a4e186df3317f192f0cb2fc3a74f5448" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010002955993e8ff8190e388e94a6bb791fbe9c6388e5011c52cb587a4ebf05e", + "bytecodeHash": "0x010002619d1a0168c99f201cac7ff8b787f1975e1dd6aaf6baba68aade3d3c52", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x01000103174a90beadc2cffe3e81bdb7b8a576174e888809c1953175fd3015b4", + "bytecodeHash": "0x010000f3b310a8c54b771dc7ee43e1f6da2efa3a2b470c511a3039c130cd63cb", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005da36075675b98f85fe90df11c1d526f6b12925da3a55a8b9c02aaac5f", + "bytecodeHash": "0x0100005983e6e523fc73e5326d31e0e96fa440fec2818e923fe57a48688617aa", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000d97de8c14cd36b1ce06cd7f44a09f6093ec8eb4041629c0fc2116d0c73", + "bytecodeHash": "0x010000cfd785169945521d4d3bece055ed7c88b79eabdc7bda73f62583bd844c", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x010000470e396f376539289b7975b6866914a8a0994008a02987edac8be81db7", + "bytecodeHash": "0x010000411cea63a93f499cb4b434c13c9c0300126fe1c2714e1755c10889072c", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a5eabf9e28288b7ab7e1db316148021347460cfb4314570956867d5af5", + "bytecodeHash": "0x010001a5d85e6baddaf82e2d7a43974ab3ad285facf4c3e28844adfc0125a0ce", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { "contractName": "EventWriter", - "bytecodePath": "contracts-preprocessed/artifacts/EventWriter.yul.zbin", + "bytecodePath": "contracts-preprocessed/artifacts/EventWriter.yul/EventWriter.yul.zbin", "sourceCodePath": "contracts-preprocessed/EventWriter.yul", - "bytecodeHash": "0x010000159b30cba9e2096353695b63ca5cbf566416a545a6bcb2ff2e4e672f98", + "bytecodeHash": "0x0100001739ee6f13091800b6cac4bd0c2c81dd81b449b6ddf3e663ce098c60ad", "sourceCodeHash": "0xfcf4828bcc109dea5f88c38f428d9ac5e18d5a2767fa4909277802c7e38c1f93" }, { "contractName": "CodeOracle", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/CodeOracle.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/CodeOracle.yul/CodeOracle.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/CodeOracle.yul", - "bytecodeHash": "0x01000023d652655672eafbb0adc385bd423a4a59f752a28f3dde16e74fa205e3", + "bytecodeHash": "0x010000210cd0b1ab22d71e01091a15cb8190e30d884784b092640d83aaf6c462", "sourceCodeHash": "0x476063e7907f2b7a532c4da6f606fa07186b5a10d77af8fdd83dbea3d9f23f93" }, { "contractName": "EcAdd", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcAdd.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcAdd.yul/EcAdd.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/EcAdd.yul", - "bytecodeHash": "0x01000087be6181fcb16bebb0567c58b658eec345822aec1d42d471e84f758b85", + "bytecodeHash": "0x01000085f63553694e753270541123b5e2c2b809f1b883db3ceb830366524a40", "sourceCodeHash": "0xdfec1c5f8c6a93df1c8821f1ac15058a18a640bcbdeb67dc4a017f2153ff1c86" }, { "contractName": "EcMul", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcMul.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcMul.yul/EcMul.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/EcMul.yul", - "bytecodeHash": "0x010000bd553a916fcda3726f7b6b3ccfc17887166982915ced63abc78ba43b66", + "bytecodeHash": "0x010000bbf677d3be4dbbf5dad75e63e87f2b1baf1b457d2507cb58025e26a2bf", "sourceCodeHash": "0x0e3f320c8a9532425b85809bf0a2136e707046a01bf20491ec03c77887516c43" }, { "contractName": "EcPairing", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcPairing.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcPairing.yul/EcPairing.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/EcPairing.yul", - "bytecodeHash": "0x01000f1b5f8dd50a00b502d2663746a49a81a01857b6ee1e1b38c9959142b299", + "bytecodeHash": "0x01000ef38d94382bae33b3ffc36660e56b2df54c49c32963f49153830c36121e", "sourceCodeHash": "0x5d008cedc44e0e52c2567fd2b877916b2ec5e7c80294cf99b66485e50a6f2c12" }, { "contractName": "Ecrecover", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Ecrecover.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Ecrecover.yul/Ecrecover.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/Ecrecover.yul", - "bytecodeHash": "0x010000113d6b03e34605f26aa1fc6fb8953561eb55bb5ea192a5a38f7de3053b", + "bytecodeHash": "0x01000013ffc212bb76a7b9108abff6be1d0746154e36d32e9c69268ef95e556a", "sourceCodeHash": "0x21e03ab7a5f518a21258669c82506b1d4d1141f8fd4f30bb385f9730580ddd3c" }, { "contractName": "Keccak256", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Keccak256.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Keccak256.yul/Keccak256.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/Keccak256.yul", - "bytecodeHash": "0x0100000ff991d5847f1e9c10c5969d0f03b34a25411ad86d5cb3e0d9c3931e0b", + "bytecodeHash": "0x0100000f16ef9261284d26f08a560cd482ff7eb7944fe37ac99113aa4eb75188", "sourceCodeHash": "0xb454e7760732ce1fffc75174c8cf54dca422206cf1e52a29d274b310b574f26d" }, { "contractName": "P256Verify", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/P256Verify.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/P256Verify.yul/P256Verify.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/P256Verify.yul", - "bytecodeHash": "0x010000116595cfcc96291f95d47ede2ce630f25ccbd7428f00dc7f8135fb565a", + "bytecodeHash": "0x0100000ff914846f07b729f21be741f039c13d9c8e7c53e4db3a4c9a9f7e022d", "sourceCodeHash": "0x976b68d0362307313fd1aaea309eaa2d849187f37da451618c70dd3a6ac3cf3c" }, { "contractName": "SHA256", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/SHA256.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/SHA256.yul/SHA256.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/SHA256.yul", - "bytecodeHash": "0x010000171e4e61b14feacd43cb555bffa5f194d38117132957708dcef83ac15a", + "bytecodeHash": "0x01000017cac2faad1aa8a1fd865fa464fbf092dbd8031dedb52fa6b8632e5b97", "sourceCodeHash": "0xfd4290467e26e992f39db9ca132e78ce99ce042b0254a368f1d7832dc94ddefb" }, { "contractName": "bootloader_test", - "bytecodePath": "bootloader/build/artifacts/bootloader_test.yul.zbin", + "bytecodePath": "bootloader/build/artifacts/bootloader_test.yul/bootloader_test.yul.zbin", "sourceCodePath": "bootloader/build/bootloader_test.yul", - "bytecodeHash": "0x010003cbe67434b2848054322cbc311385851bbfbf70d17f92cd5f1f9836b25e", + "bytecodeHash": "0x010003ade02adac2c039832861a6649c6cbb7abbb2ff8542c6aefff7bde06a9c", "sourceCodeHash": "0x006fdf461899dec5fdb34301c23e6819eb93e275907cbfc67d73fccfb47cae68" }, { "contractName": "fee_estimate", - "bytecodePath": "bootloader/build/artifacts/fee_estimate.yul.zbin", + "bytecodePath": "bootloader/build/artifacts/fee_estimate.yul/fee_estimate.yul.zbin", "sourceCodePath": "bootloader/build/fee_estimate.yul", - "bytecodeHash": "0x0100092d9b8ae575bca569f68fe60fbef1dc7d4aad6aa02cc4836f56afcf0a38", + "bytecodeHash": "0x01000905327a3aeb212816e7e0f6c16c5acc491c714c06d823c4bbc7075b62d6", "sourceCodeHash": "0x8a858319bac2924a3dee778218a7fe5e23898db0d87b02d7b783f94c5a02d257" }, { "contractName": "gas_test", - "bytecodePath": "bootloader/build/artifacts/gas_test.yul.zbin", + "bytecodePath": "bootloader/build/artifacts/gas_test.yul/gas_test.yul.zbin", "sourceCodePath": "bootloader/build/gas_test.yul", - "bytecodeHash": "0x010008b3e1b8bdd393f2f8d6f5c994c8b9c287df7310dee75d0c52a245fc7cb1", + "bytecodeHash": "0x01000871cdb46e23c5b65176cd772e368d255c80290058b89e9644efbe8d7c53", "sourceCodeHash": "0x89f5ad470f10e755fa57b82507518e571c24409a328bc33aeba26e9518ad1c3e" }, { "contractName": "playground_batch", - "bytecodePath": "bootloader/build/artifacts/playground_batch.yul.zbin", + "bytecodePath": "bootloader/build/artifacts/playground_batch.yul/playground_batch.yul.zbin", "sourceCodePath": "bootloader/build/playground_batch.yul", - "bytecodeHash": "0x01000933061c23d700f3f647c45068e22f5506ff33bb516ac13f11069b163986", + "bytecodeHash": "0x01000909408f87054598e7a1e9fbc58e0e9733b0ab5030618eef36ef746cac68", "sourceCodeHash": "0x769448c4fd2b65c43d758ca5f34dd29d9b9dd3000fd0ec89cffcaf8d365a64fd" }, { "contractName": "proved_batch", - "bytecodePath": "bootloader/build/artifacts/proved_batch.yul.zbin", + "bytecodePath": "bootloader/build/artifacts/proved_batch.yul/proved_batch.yul.zbin", "sourceCodePath": "bootloader/build/proved_batch.yul", - "bytecodeHash": "0x010008c3be57ae5800e077b6c2056d9d75ad1a7b4f0ce583407961cc6fe0b678", + "bytecodeHash": "0x01000881f046342b70470a7e81423b5903dfe06669d01292e7dc6f8eb73bf404", "sourceCodeHash": "0x908bc6ddb34ef89b125e9637239a1149deacacd91255781d82a65a542a39036e" } ] diff --git a/system-contracts/bootloader/test_infra/Cargo.lock b/system-contracts/bootloader/test_infra/Cargo.lock index 6fa43fd45..f7a9e30ee 100644 --- a/system-contracts/bootloader/test_infra/Cargo.lock +++ b/system-contracts/bootloader/test_infra/Cargo.lock @@ -2,26 +2,37 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addchain" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" +dependencies = [ + "num-bigint 0.3.3", + "num-integer", + "num-traits", +] + [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -30,12 +41,11 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if 1.0.0", - "getrandom", + "cfg-if", "once_cell", "version_check", "zerocopy", @@ -43,18 +53,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -73,15 +83,45 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "arr_macro" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a105bfda48707cf19220129e78fca01e9639433ffaef4163546ed8fb04120a5" +dependencies = [ + "arr_macro_impl", + "proc-macro-hack", +] + +[[package]] +name = "arr_macro_impl" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "0609c78bd572f4edc74310dfb63a01f5609d53fa8b4dd7c4d98aef3b3e8d72d1" +dependencies = [ + "proc-macro-hack", + "quote 1.0.37", + "syn 1.0.109", +] [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] [[package]] name = "arrayvec" @@ -91,19 +131,41 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", +] [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -116,35 +178,30 @@ dependencies = [ ] [[package]] -name = "atomic-write-file" -version = "0.1.2" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436" -dependencies = [ - "nix", - "rand 0.8.5", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.6.20" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", - "bitflags 1.3.2", "bytes", "futures-util", - "http", - "http-body", - "hyper", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", "itoa", "matchit", "memchr", @@ -153,42 +210,57 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper", - "tower", + "sync_wrapper 1.0.1", + "tower 0.5.1", "tower-layer", "tower-service", ] [[package]] name = "axum-core" -version = "0.3.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", ] +[[package]] +name = "backon" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d67782c3f868daa71d3533538e98a8e13713231969def7536e8039606fc46bf0" +dependencies = [ + "fastrand", + "futures-core", + "pin-project", + "tokio", +] + [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -211,9 +283,15 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -227,36 +305,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" -[[package]] -name = "bellman_ce" -version = "0.3.2" -source = "git+https://github.com/matter-labs/bellman?branch=dev#5520aa2274afe73d281373c92b007a2ecdebfbea" -dependencies = [ - "arrayvec 0.7.4", - "bit-vec", - "blake2s_const", - "blake2s_simd", - "byteorder", - "cfg-if 1.0.0", - "crossbeam 0.7.3", - "futures", - "hex", - "lazy_static", - "num_cpus", - "pairing_ce 0.28.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6", - "serde", - "smallvec", - "tiny-keccak 1.5.0", -] - [[package]] name = "bigdecimal" -version = "0.3.1" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" +checksum = "51d712318a27c7150326677b321a5fa91b55f6d9034ffd67f20319e147d40cee" dependencies = [ - "num-bigint", + "autocfg", + "libm", + "num-bigint 0.4.6", "num-integer", "num-traits", ] @@ -283,12 +340,12 @@ dependencies = [ "lazycell", "peeking_take_while", "prettyplease", - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "regex", "rustc-hash", "shlex", - "syn 2.0.40", + "syn 2.0.79", ] [[package]] @@ -308,9 +365,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -329,31 +386,44 @@ dependencies = [ [[package]] name = "blake2" -version = "0.10.6" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174" dependencies = [ - "digest 0.10.7", + "crypto-mac", + "digest 0.9.0", + "opaque-debug", ] [[package]] name = "blake2" version = "0.10.6" -source = "git+https://github.com/RustCrypto/hashes.git?rev=1f727ce37ff40fa0cce84eb8543a45bdd3ca4a4e#1f727ce37ff40fa0cce84eb8543a45bdd3ca4a4e" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ "digest 0.10.7", ] [[package]] -name = "blake2s_const" -version = "0.6.0" -source = "git+https://github.com/matter-labs/bellman?branch=dev#5520aa2274afe73d281373c92b007a2ecdebfbea" +name = "blake2-rfc_bellman_edition" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc60350286c7c3db13b98e91dbe5c8b6830a6821bc20af5b0c310ce94d74915" dependencies = [ - "arrayref", - "arrayvec 0.5.2", + "arrayvec 0.4.12", + "byteorder", "constant_time_eq", ] +[[package]] +name = "blake2_ce" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90cef65f11dd09a6c58914148161dbf190e5dcc02c87ed2aa47b3b97d3e7ce76" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "blake2s_simd" version = "0.5.11" @@ -371,6 +441,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ + "block-padding", "generic-array", ] @@ -383,11 +454,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + [[package]] name = "blst" -version = "0.3.11" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874" dependencies = [ "cc", "glob", @@ -397,17 +474,17 @@ dependencies = [ [[package]] name = "boojum" -version = "0.2.0" -source = "git+https://github.com/matter-labs/era-boojum.git?branch=main#19988079852ea22576da6b09e39365e6cdc1368f" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ec2f007ff8f90cc459f03e9f30ca1065440170f013c868823646e2e48d0234" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bincode", - "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2 0.10.6", "const_format", "convert_case", - "crossbeam 0.8.2", + "crossbeam", "crypto-bigint 0.5.5", - "cs_derive", "derivative", "ethereum-types", "firestorm", @@ -415,22 +492,22 @@ dependencies = [ "lazy_static", "num-modular", "num_cpus", - "packed_simd", - "pairing_ce 0.28.5 (git+https://github.com/matter-labs/pairing.git)", "rand 0.8.5", "rayon", "serde", "sha2 0.10.8", - "sha3 0.10.6", + "sha3_ce", "smallvec", "unroll", + "zksync_cs_derive", + "zksync_pairing", ] [[package]] name = "borsh" -version = "1.3.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d4d6dafc1a3bb54687538972158f07b2c948bc57d5890df22c0739098b3028" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", "cfg_aliases", @@ -438,23 +515,23 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.3.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4918709cc4dd777ad2b6303ed03cb37f3ca0ccede8c1b0d28ac6db8f4710e0" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ "once_cell", - "proc-macro-crate 2.0.1", - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", "syn_derive", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-slice-cast" @@ -464,9 +541,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytecheck" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -475,20 +552,20 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "bytecount" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" +checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "byteorder" @@ -498,9 +575,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "bzip2-sys" @@ -515,18 +592,18 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -546,12 +623,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "58e804ac3194a48bb129643eb1d62fcc20d18c6b8c181704489353d13120bcd1" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -563,12 +641,6 @@ dependencies = [ "nom", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -577,15 +649,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -593,121 +665,130 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "circuit_encodings" -version = "0.1.40" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.0#39665dffd576cff5007c80dd0e1b5334e230bd3b" +version = "0.140.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf6b7cc842eadb4c250cdc6a8bc1dd97624d9f08bbe54db3e11fb23c3a72be07" dependencies = [ "derivative", "serde", - "zk_evm 1.4.0", - "zkevm_circuits 1.4.0", + "zk_evm 0.140.0", + "zkevm_circuits 0.140.3", ] [[package]] name = "circuit_encodings" -version = "0.1.41" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.1#f7bd71fd4216e2c51ab7b09a95909fe48c75f35b" +version = "0.141.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7898ffbf3cd413576b4b674fe1545a35488c67eb16bd5a4148425e42c2a2b65b" dependencies = [ "derivative", "serde", - "zk_evm 1.4.1", - "zkevm_circuits 1.4.1", + "zk_evm 0.141.0", + "zkevm_circuits 0.141.2", ] [[package]] name = "circuit_encodings" -version = "0.1.42" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.2#3149a162a729581005fbad6dbcef027a3ee1b214" +version = "0.142.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8364ecafcc4b2c896023f8d3af952c52a500aa55f14fd268bb5d9ab07f837369" dependencies = [ "derivative", "serde", - "zk_evm 1.4.1", - "zkevm_circuits 1.4.1", + "zk_evm 0.141.0", + "zkevm_circuits 0.141.2", ] [[package]] name = "circuit_encodings" -version = "0.1.50" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.5.0#394e1c7d1aec06d2f3abd63bdc2ddf0efef5ac49" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67617688c66640c84f9b98ff26d48f7898dca4faeb45241a4f21ec333788e7b" dependencies = [ "derivative", "serde", - "zk_evm 1.5.0", - "zkevm_circuits 1.5.0", + "zk_evm 0.150.5", + "zkevm_circuits 0.150.5", ] [[package]] name = "circuit_sequencer_api" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.3.3#aba8f2a32767b79838aca7d7d00d9d23144df32f" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb959b1f8c6bbd8be711994d182e85452a26a5d2213a709290b71c8262af1331" dependencies = [ - "bellman_ce", "derivative", "rayon", "serde", - "zk_evm 1.3.3 (git+https://github.com/matter-labs/era-zk_evm.git?branch=v1.3.3)", + "zk_evm 0.133.0", + "zksync_bellman", ] [[package]] name = "circuit_sequencer_api" -version = "0.1.40" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.0#39665dffd576cff5007c80dd0e1b5334e230bd3b" +version = "0.140.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa5f22311ce609d852d7d9f4943535ea4610aeb785129ae6ff83d5201c4fb387" dependencies = [ - "bellman_ce", - "circuit_encodings 0.1.40", + "circuit_encodings 0.140.3", "derivative", "rayon", "serde", - "zk_evm 1.4.0", + "zk_evm 0.140.0", + "zksync_bellman", ] [[package]] name = "circuit_sequencer_api" -version = "0.1.41" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.1#f7bd71fd4216e2c51ab7b09a95909fe48c75f35b" +version = "0.141.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c47c71d6ba83a8beb0af13af70beffd627f5497caf3d44c6f96363e788b07ea" dependencies = [ - "bellman_ce", - "circuit_encodings 0.1.41", + "circuit_encodings 0.141.2", "derivative", "rayon", "serde", - "zk_evm 1.4.1", + "zk_evm 0.141.0", + "zksync_bellman", ] [[package]] name = "circuit_sequencer_api" -version = "0.1.42" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.2#3149a162a729581005fbad6dbcef027a3ee1b214" +version = "0.142.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e264723359e6a1aad98110bdccf1ae3ad596e93e7d31da9e40f6adc07e4add54" dependencies = [ - "bellman_ce", - "circuit_encodings 0.1.42", + "circuit_encodings 0.142.2", "derivative", "rayon", "serde", - "zk_evm 1.4.1", + "zk_evm 0.141.0", + "zksync_bellman", ] [[package]] name = "circuit_sequencer_api" -version = "0.1.50" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.5.0#394e1c7d1aec06d2f3abd63bdc2ddf0efef5ac49" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21017310971d4a051e4a52ad70eed11d1ae69defeca8314f73a3a4bad16705a9" dependencies = [ - "bellman_ce", - "circuit_encodings 0.1.50", + "circuit_encodings 0.150.5", "derivative", "rayon", "serde", + "zksync_bellman", ] [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -730,30 +811,39 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bed69047ed42e52c7e38d6421eeb8ceefb4f2a2b52eed59137f7bad7908f6800" +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const_format" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 1.0.87", + "quote 1.0.37", + "unicode-xid 0.2.6", ] [[package]] @@ -764,9 +854,12 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "convert_case" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "core-foundation" @@ -780,24 +873,24 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc" -version = "3.0.1" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] @@ -809,143 +902,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] -name = "crossbeam" -version = "0.7.3" +name = "crc32fast" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if 0.1.10", - "crossbeam-channel 0.4.4", - "crossbeam-deque 0.7.4", - "crossbeam-epoch 0.8.2", - "crossbeam-queue 0.2.3", - "crossbeam-utils 0.7.2", + "cfg-if", ] [[package]] name = "crossbeam" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-channel 0.5.8", - "crossbeam-deque 0.8.3", - "crossbeam-epoch 0.9.15", - "crossbeam-queue 0.3.8", - "crossbeam-utils 0.8.16", -] - -[[package]] -name = "crossbeam-channel" -version = "0.4.4" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" dependencies = [ - "crossbeam-utils 0.7.2", - "maybe-uninit", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.16", + "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" -dependencies = [ - "crossbeam-epoch 0.8.2", - "crossbeam-utils 0.7.2", - "maybe-uninit", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch 0.9.15", - "crossbeam-utils 0.8.16", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "lazy_static", - "maybe-uninit", - "memoffset 0.5.6", - "scopeguard", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if 1.0.0", - "crossbeam-utils 0.8.16", - "memoffset 0.9.0", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.2.3" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "maybe-uninit", + "crossbeam-utils", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.16", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", + "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -988,28 +1007,36 @@ dependencies = [ ] [[package]] -name = "cs_derive" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-boojum.git?branch=main#19988079852ea22576da6b09e39365e6cdc1368f" +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", + "generic-array", + "subtle", +] + +[[package]] +name = "ctor" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" +dependencies = [ + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -1021,9 +1048,44 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", +] + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2 1.0.87", + "quote 1.0.37", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote 1.0.37", + "syn 1.0.109", ] [[package]] @@ -1032,8 +1094,8 @@ version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if 1.0.0", - "hashbrown 0.14.3", + "cfg-if", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -1061,9 +1123,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", @@ -1072,11 +1134,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -1085,44 +1148,37 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "derive_more" -version = "0.99.17" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", + "derive_more-impl", ] [[package]] -name = "derive_more" -version = "1.0.0-beta.6" +name = "derive_more-impl" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7abbfc297053be59290e3152f8cbcd52c8642e0728b69ee187d991d4c1af08d" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ - "derive_more-impl", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", + "unicode-xid 0.2.6", ] [[package]] -name = "derive_more-impl" -version = "1.0.0-beta.6" +name = "diff" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bba3e9872d7c58ce7ef0fcf1844fcc3e23ef2a58377b50df35dd98e42a5726e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", - "unicode-xid", -] +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" @@ -1175,7 +1231,7 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der 0.7.8", + "der 0.7.9", "digest 0.10.7", "elliptic-curve 0.13.8", "rfc6979 0.4.0", @@ -1195,9 +1251,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", @@ -1210,9 +1266,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" dependencies = [ "serde", ] @@ -1259,20 +1315,32 @@ dependencies = [ [[package]] name = "elsa" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714f766f3556b44e7e4776ad133fcc3445a489517c25c704ace411bb14790194" +checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10" dependencies = [ "stable_deref_trait", ] [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" dependencies = [ - "cfg-if 1.0.0", + "once_cell", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -1292,9 +1360,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1315,7 +1383,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "home", "windows-sys 0.48.0", ] @@ -1366,15 +1434,20 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.3" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "ff" @@ -1396,39 +1469,11 @@ dependencies = [ "subtle", ] -[[package]] -name = "ff_ce" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b538e4231443a5b9c507caee3356f016d832cf7393d2d90f03ea3180d4e3fbc" -dependencies = [ - "byteorder", - "ff_derive_ce", - "hex", - "rand 0.4.6", - "serde", -] - -[[package]] -name = "ff_derive_ce" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96fbccd88dbb1fac4ee4a07c2fcc4ca719a74ffbd9d2b9d41d8c8eb073d8b20" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", - "proc-macro2", - "quote", - "serde", - "syn 1.0.109", -] - [[package]] name = "fiat-crypto" -version = "0.2.5" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "findshlibs" @@ -1442,12 +1487,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "finl_unicode" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" - [[package]] name = "firestorm" version = "0.5.1" @@ -1472,6 +1511,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "flume" version = "0.11.0" @@ -1480,7 +1529,7 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.8", + "spin", ] [[package]] @@ -1513,6 +1562,39 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "franklin-crypto" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "971289216ea5c91872e5e0bb6989214b537bbce375d09fabea5c3ccfe031b204" +dependencies = [ + "arr_macro", + "bit-vec", + "blake2 0.9.2", + "blake2-rfc_bellman_edition", + "blake2s_simd", + "boojum", + "byteorder", + "derivative", + "digest 0.9.0", + "hex", + "indexmap 1.9.3", + "itertools 0.10.5", + "lazy_static", + "num-bigint 0.4.6", + "num-derive", + "num-integer", + "num-traits", + "rand 0.4.6", + "serde", + "sha2 0.9.9", + "sha3 0.9.1", + "smallvec", + "splitmut", + "tiny-keccak 1.5.0", + "zksync_bellman", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -1527,9 +1609,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1542,9 +1624,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1552,15 +1634,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1581,44 +1663,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" - -[[package]] -name = "futures-timer" -version = "3.0.2" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1645,20 +1721,22 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -1666,6 +1744,81 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "google-cloud-auth" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1112c453c2e155b3e683204ffff52bcc6d6495d04b68d9e90cd24161270c5058" +dependencies = [ + "async-trait", + "base64 0.21.7", + "google-cloud-metadata", + "google-cloud-token", + "home", + "jsonwebtoken", + "reqwest 0.12.8", + "serde", + "serde_json", + "thiserror", + "time", + "tokio", + "tracing", + "urlencoding", +] + +[[package]] +name = "google-cloud-metadata" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f945a208886a13d07636f38fb978da371d0abc3e34bad338124b9f8c135a8f" +dependencies = [ + "reqwest 0.12.8", + "thiserror", + "tokio", +] + +[[package]] +name = "google-cloud-storage" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc0c5b7469142d91bd77959e69375bede324a5def07c7f29aa0d582586cba305" +dependencies = [ + "anyhow", + "async-stream", + "async-trait", + "base64 0.21.7", + "bytes", + "futures-util", + "google-cloud-auth", + "google-cloud-metadata", + "google-cloud-token", + "hex", + "once_cell", + "percent-encoding", + "pkcs8 0.10.2", + "regex", + "reqwest 0.12.8", + "reqwest-middleware", + "ring", + "serde", + "serde_json", + "sha2 0.10.8", + "thiserror", + "time", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "google-cloud-token" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c12ba8b21d128a2ce8585955246977fbce4415f680ebf9199b6f9d6d725f" +dependencies = [ + "async-trait", +] + [[package]] name = "group" version = "0.12.1" @@ -1690,17 +1843,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", - "indexmap 2.1.0", + "http 0.2.12", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -1708,64 +1861,70 @@ dependencies = [ ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "h2" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ - "ahash 0.7.7", + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", ] [[package]] -name = "hashbrown" -version = "0.14.3" +name = "handlebars" +version = "3.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "4498fc115fa7d34de968184e473529abb40eeb6be8bc5f7faba3d08c316cb3e3" dependencies = [ - "ahash 0.8.6", - "allocator-api2", + "log", + "pest", + "pest_derive", + "quick-error", + "serde", + "serde_json", ] [[package]] -name = "hashlink" -version = "0.8.4" +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "hashbrown 0.14.3", + "ahash 0.7.8", ] [[package]] -name = "headers" -version = "0.3.9" +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "base64 0.21.5", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", + "ahash 0.8.11", + "allocator-api2", ] [[package]] -name = "headers-core" -version = "0.2.0" +name = "hashbrown" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "heck" -version = "0.4.1" +name = "hashlink" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "unicode-segmentation", + "hashbrown 0.14.5", ] [[package]] @@ -1776,9 +1935,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1788,9 +1947,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hkdf" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ "hmac", ] @@ -1806,11 +1965,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1826,9 +1985,20 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -1842,15 +2012,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1860,52 +2053,77 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-rustls" -version = "0.24.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", - "http", - "hyper", + "http 1.1.0", + "hyper 1.4.1", + "hyper-util", "rustls", + "rustls-pki-types", "tokio", "tokio-rustls", + "tower-service", ] [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper", + "hyper 1.4.1", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] @@ -1915,17 +2133,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.30", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.4.1", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.4.1", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1945,14 +2198,10 @@ dependencies = [ ] [[package]] -name = "idna" -version = "0.4.0" +name = "ident_case" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" @@ -1997,8 +2246,8 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] @@ -2014,19 +2263,19 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.15.0", ] [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "ipnetwork" @@ -2048,59 +2297,59 @@ dependencies = [ [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itertools" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] [[package]] -name = "jsonrpc-core" -version = "18.0.0" +name = "jsonwebtoken" +version = "9.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" dependencies = [ - "futures", - "futures-executor", - "futures-util", - "log", + "base64 0.21.7", + "js-sys", + "pem", + "ring", "serde", - "serde_derive", "serde_json", + "simple_asn1", ] [[package]] @@ -2109,7 +2358,7 @@ version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa 0.14.8", "elliptic-curve 0.12.3", "sha2 0.10.8", @@ -2117,11 +2366,11 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa 0.16.9", "elliptic-curve 0.13.8", "once_cell", @@ -2131,20 +2380,20 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] @@ -2155,18 +2404,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ - "cfg-if 1.0.0", - "winapi", + "cfg-if", + "windows-targets 0.52.6", ] [[package]] @@ -2193,9 +2442,9 @@ dependencies = [ [[package]] name = "libsqlite3-sys" -version = "0.27.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" dependencies = [ "cc", "pkg-config", @@ -2204,46 +2453,26 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.12" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "pkg-config", "vcpkg", ] -[[package]] -name = "linkme" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e6b0bb9ca88d3c5ae88240beb9683821f903b824ee8381ef9ab4e8522fbfa9" -dependencies = [ - "linkme-impl", -] - -[[package]] -name = "linkme-impl" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b3f61e557a617ec6ba36c79431e1f3b5e100d67cfbdb61ed6ef384298af016" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", -] - [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -2251,9 +2480,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "logos" @@ -2272,10 +2501,10 @@ checksum = "dc487311295e0002e452025d6b580b77bb17286de87b57138f3b5db711cded68" dependencies = [ "beef", "fnv", - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "regex-syntax 0.6.29", - "syn 2.0.40", + "syn 2.0.79", ] [[package]] @@ -2289,9 +2518,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.9.4" +version = "1.11.1+lz4-1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" dependencies = [ "cc", "libc", @@ -2318,45 +2547,21 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "md-5" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "digest 0.10.7", ] [[package]] name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memoffset" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.9.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miette" @@ -2376,9 +2581,9 @@ version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -2387,14 +2592,24 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "mini-moka" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e0b72e7c9042467008b10279fc732326bd605459ae03bda88825909dd19b56" +checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803" dependencies = [ - "crossbeam-channel 0.5.8", - "crossbeam-utils 0.8.16", + "crossbeam-channel", + "crossbeam-utils", "dashmap", "skeptic", "smallvec", @@ -2410,66 +2625,37 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.10" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "multivm" -version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" -dependencies = [ - "anyhow", - "circuit_sequencer_api 0.1.0", - "circuit_sequencer_api 0.1.40", - "circuit_sequencer_api 0.1.41", - "circuit_sequencer_api 0.1.42", - "circuit_sequencer_api 0.1.50", - "hex", - "itertools 0.10.5", - "once_cell", - "thiserror", - "tracing", - "vise", - "zk_evm 1.3.1", - "zk_evm 1.3.3 (git+https://github.com/matter-labs/era-zk_evm.git?tag=v1.3.3-rc2)", - "zk_evm 1.4.0", - "zk_evm 1.4.1", - "zk_evm 1.5.0", - "zksync_contracts", - "zksync_state", - "zksync_system_constants", - "zksync_types", - "zksync_utils", -] +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -2482,15 +2668,10 @@ dependencies = [ ] [[package]] -name = "nix" -version = "0.27.1" +name = "nodrop" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.4.1", - "cfg-if 1.0.0", - "libc", -] +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] name = "nom" @@ -2514,11 +2695,11 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "num-bigint", + "num-bigint 0.4.6", "num-complex", "num-integer", "num-iter", @@ -2528,13 +2709,23 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" dependencies = [ "autocfg", "num-integer", "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", "serde", ] @@ -2557,29 +2748,45 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", "serde", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-derive" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -2598,12 +2805,11 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", - "num-bigint", + "num-bigint 0.4.6", "num-integer", "num-traits", "serde", @@ -2611,9 +2817,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -2640,11 +2846,11 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ - "num_enum_derive 0.7.2", + "num_enum_derive 0.7.3", ] [[package]] @@ -2654,52 +2860,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 2.0.1", - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "object" -version = "0.32.1" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.61" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.4.1", - "cfg-if 1.0.0", + "bitflags 2.6.0", + "cfg-if", "foreign-types", "libc", "once_cell", @@ -2713,9 +2919,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -2726,9 +2932,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.97" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -2738,43 +2944,58 @@ dependencies = [ [[package]] name = "opentelemetry" -version = "0.20.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" +checksum = "4c365a63eec4f55b7efeceb724f1336f26a9cf3427b70e59e2cd2a5b947fba96" dependencies = [ - "opentelemetry_api", - "opentelemetry_sdk", + "futures-core", + "futures-sink", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", +] + +[[package]] +name = "opentelemetry-appender-tracing" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84de945cb3a6f1e0d6317cbd998bbd0519ab00f4b790db67e0ff4fdcf7cedb6" +dependencies = [ + "opentelemetry", + "tracing", + "tracing-core", + "tracing-subscriber", ] [[package]] name = "opentelemetry-http" -version = "0.9.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7594ec0e11d8e33faf03530a4c49af7064ebba81c1480e01be67d90b356508b" +checksum = "ad31e9de44ee3538fb9d64fe3376c1362f406162434609e79aea2a41a0af78ab" dependencies = [ "async-trait", "bytes", - "http", - "opentelemetry_api", - "reqwest", + "http 1.1.0", + "opentelemetry", + "reqwest 0.12.8", ] [[package]] name = "opentelemetry-otlp" -version = "0.13.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5e5a5c4135864099f3faafbe939eb4d7f9b80ebf68a8448da961b32a7c1275" +checksum = "6b925a602ffb916fb7421276b86756027b37ee708f9dce2dbdcc51739f07e727" dependencies = [ "async-trait", "futures-core", - "http", + "http 1.1.0", + "opentelemetry", "opentelemetry-http", "opentelemetry-proto", - "opentelemetry-semantic-conventions", - "opentelemetry_api", "opentelemetry_sdk", - "prost 0.11.9", - "reqwest", + "prost 0.13.3", + "reqwest 0.12.8", "thiserror", "tokio", "tonic", @@ -2782,58 +3003,37 @@ dependencies = [ [[package]] name = "opentelemetry-proto" -version = "0.3.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e3f814aa9f8c905d0ee4bde026afd3b2577a97c10e1699912e3e44f0c4cbeb" +checksum = "30ee9f20bff9c984511a02f082dc8ede839e4a9bf15cc2487c8d6fea5ad850d9" dependencies = [ - "opentelemetry_api", + "opentelemetry", "opentelemetry_sdk", - "prost 0.11.9", + "prost 0.13.3", "tonic", ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.12.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c9f9340ad135068800e7f1b24e9e09ed9e7143f5bf8518ded3d3ec69789269" -dependencies = [ - "opentelemetry", -] - -[[package]] -name = "opentelemetry_api" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" -dependencies = [ - "futures-channel", - "futures-util", - "indexmap 1.9.3", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror", - "urlencoding", -] +checksum = "1cefe0543875379e47eb5f1e68ff83f45cc41366a92dfd0d073d513bf68e9a05" [[package]] name = "opentelemetry_sdk" -version = "0.20.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8e705a0612d48139799fcbaba0d4a90f06277153e43dd2bdc16c6f0edd8026" +checksum = "692eac490ec80f24a17828d49b40b60f5aeaccdfe6a503f939713afd22bc28df" dependencies = [ "async-trait", - "crossbeam-channel 0.5.8", "futures-channel", "futures-executor", "futures-util", + "glob", "once_cell", - "opentelemetry_api", - "ordered-float 3.9.2", + "opentelemetry", "percent-encoding", "rand 0.8.5", - "regex", "serde_json", "thiserror", "tokio", @@ -2849,24 +3049,15 @@ dependencies = [ "num-traits", ] -[[package]] -name = "ordered-float" -version = "3.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" -dependencies = [ - "num-traits", -] - [[package]] name = "os_info" -version = "3.7.0" +version = "3.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e" +checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" dependencies = [ "log", "serde", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -2887,60 +3078,13 @@ dependencies = [ "sha2 0.10.8", ] -[[package]] -name = "packed_simd" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f9f08af0c877571712e2e3e686ad79efad9657dbf0f7c3c8ba943ff6c38932d" -dependencies = [ - "cfg-if 1.0.0", - "num-traits", -] - -[[package]] -name = "pairing_ce" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db007b21259660d025918e653508f03050bf23fb96a88601f9936329faadc597" -dependencies = [ - "byteorder", - "cfg-if 1.0.0", - "ff_ce", - "rand 0.4.6", - "serde", -] - -[[package]] -name = "pairing_ce" -version = "0.28.5" -source = "git+https://github.com/matter-labs/pairing.git?rev=d24f2c5871089c4cd4f54c0ca266bb9fef6115eb#d24f2c5871089c4cd4f54c0ca266bb9fef6115eb" -dependencies = [ - "byteorder", - "cfg-if 1.0.0", - "ff_ce", - "rand 0.4.6", - "serde", -] - -[[package]] -name = "pairing_ce" -version = "0.28.5" -source = "git+https://github.com/matter-labs/pairing.git#d24f2c5871089c4cd4f54c0ca266bb9fef6115eb" -dependencies = [ - "byteorder", - "cfg-if 1.0.0", - "ff_ce", - "rand 0.4.6", - "serde", -] - [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bitvec", "byte-slice-cast", "impl-trait-for-tuples", @@ -2950,21 +3094,27 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.1", - "proc-macro2", - "quote", + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -2972,22 +3122,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "peeking_take_while" @@ -2995,6 +3145,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +[[package]] +name = "pem" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +dependencies = [ + "base64 0.22.1", + "serde", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -3010,41 +3170,86 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", +] + +[[package]] +name = "pest_meta" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f" +dependencies = [ + "once_cell", + "pest", + "sha2 0.10.8", +] + [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.1.0", + "indexmap 2.6.0", ] [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -3058,7 +3263,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "der 0.7.8", + "der 0.7.9", "pkcs8 0.10.2", "spki 0.7.3", ] @@ -3079,21 +3284,15 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.8", + "der 0.7.9", "spki 0.7.3", ] [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "platforms" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "powerfmt" @@ -3103,18 +3302,31 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "pretty_assertions" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] [[package]] name = "prettyplease" -version = "0.2.15" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ - "proc-macro2", - "syn 2.0.40", + "proc-macro2 1.0.87", + "syn 2.0.79", ] [[package]] @@ -3151,12 +3363,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.22.22", ] [[package]] @@ -3166,8 +3377,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", "version_check", ] @@ -3178,25 +3389,40 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "version_check", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus-client" -version = "0.22.2" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ca959da22a332509f2a73ae9e5f23f9dcfc31fd3a54d71f159495bd5909baa" +checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" dependencies = [ "dtoa", "itoa", @@ -3210,77 +3436,76 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "prost" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive 0.11.9", + "prost-derive 0.12.6", ] [[package]] name = "prost" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", - "prost-derive 0.12.3", + "prost-derive 0.13.3", ] [[package]] name = "prost-build" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.4.1", - "itertools 0.11.0", + "heck", + "itertools 0.12.1", "log", "multimap", "once_cell", "petgraph", "prettyplease", - "prost 0.12.3", + "prost 0.12.6", "prost-types", "regex", - "syn 2.0.40", + "syn 2.0.79", "tempfile", - "which", ] [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", + "itertools 0.12.1", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools 0.11.0", - "proc-macro2", - "quote", - "syn 2.0.40", + "itertools 0.13.0", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -3289,11 +3514,11 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "057237efdb71cf4b3f9396302a3d6599a92fa94063ba537b66130980ea9909f3" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "logos", "miette", "once_cell", - "prost 0.12.3", + "prost 0.12.6", "prost-types", "serde", "serde-value", @@ -3301,11 +3526,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ - "prost 0.12.3", + "prost 0.12.6", ] [[package]] @@ -3316,7 +3541,7 @@ checksum = "00bb76c5f6221de491fe2c8f39b106330bbd9762c6511119c07940e10eb9ff11" dependencies = [ "bytes", "miette", - "prost 0.12.3", + "prost 0.12.6", "prost-reflect", "prost-types", "protox-parse", @@ -3350,22 +3575,28 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "pulldown-cmark" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "memchr", "unicase", ] +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-protobuf" version = "0.8.1" @@ -3377,11 +3608,20 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.87", ] [[package]] @@ -3450,9 +3690,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -3460,12 +3700,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-deque 0.8.3", - "crossbeam-utils 0.8.16", + "crossbeam-deque", + "crossbeam-utils", ] [[package]] @@ -3479,23 +3719,23 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -3509,13 +3749,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", ] [[package]] @@ -3526,36 +3766,35 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rend" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" dependencies = [ "bytecheck", ] [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "hyper-tls", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.30", + "hyper-tls 0.5.0", "ipnet", "js-sys", "log", @@ -3564,24 +3803,109 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", - "system-configuration", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", "tokio", "tokio-native-tls", - "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", "winreg", ] +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-rustls", + "hyper-tls 0.6.0", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.2.0", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "system-configuration 0.6.1", + "tokio", + "tokio-native-tls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "windows-registry", +] + +[[package]] +name = "reqwest-middleware" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562ceb5a604d3f7c885a792d42c199fd8af239d0a51b2fa6a78aafa092452b04" +dependencies = [ + "anyhow", + "async-trait", + "http 1.1.0", + "reqwest 0.12.8", + "serde", + "thiserror", + "tower-service", +] + +[[package]] +name = "rescue_poseidon" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82900c877a0ba5362ac5756efbd82c5b795dc509011c1253e2389d8708f1389d" +dependencies = [ + "addchain", + "arrayvec 0.7.6", + "blake2 0.10.6", + "byteorder", + "derivative", + "franklin-crypto", + "lazy_static", + "log", + "num-bigint 0.3.3", + "num-integer", + "num-iter", + "num-traits", + "rand 0.4.6", + "serde", + "sha3 0.9.1", + "smallvec", + "typemap_rev", +] + [[package]] name = "rfc6979" version = "0.3.1" @@ -3605,23 +3929,24 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", - "spin 0.9.8", + "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "rkyv" -version = "0.7.43" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527a97cdfef66f65998b5f3b637c26f5a5ec09cc52a3f9932313ac645f4190f5" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" dependencies = [ "bitvec", "bytecheck", @@ -3637,12 +3962,12 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.43" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5c462a1328c8e67e4d6dbad1eb0355dd43e8ab432c6e227a43657f16ade5033" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] @@ -3688,11 +4013,11 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.33.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06676aec5ccb8fc1da723cc8c0f9a46549f21ebb8753d3915c6c41db1e7f1dc4" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "borsh", "bytes", "num-traits", @@ -3704,9 +4029,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -3722,20 +4047,20 @@ checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -3744,14 +4069,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" dependencies = [ - "log", - "ring", + "once_cell", + "rustls-pki-types", "rustls-webpki", - "sct", + "subtle", + "zeroize", ] [[package]] @@ -3760,30 +4086,46 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", ] +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + [[package]] name = "rustls-webpki" -version = "0.101.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", + "rustls-pki-types", "untrusted", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -3796,11 +4138,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -3809,16 +4151,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "seahash" version = "4.1.0" @@ -3846,7 +4178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct 0.2.0", - "der 0.7.8", + "der 0.7.9", "generic-array", "pkcs8 0.10.2", "subtle", @@ -3871,13 +4203,22 @@ dependencies = [ "cc", ] +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -3886,9 +4227,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -3896,9 +4237,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] @@ -3911,7 +4252,7 @@ checksum = "6ce4b57f1b521f674df7a1d200be8ff5d74e3712020ee25b553146657b5377d5" dependencies = [ "httpdate", "native-tls", - "reqwest", + "reqwest 0.11.27", "sentry-backtrace", "sentry-contexts", "sentry-core", @@ -4019,9 +4360,9 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -4032,28 +4373,29 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" dependencies = [ - "ordered-float 2.10.1", + "ordered-float", "serde", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -4071,29 +4413,40 @@ dependencies = [ ] [[package]] -name = "serde_yaml" -version = "0.9.29" +name = "serde_with" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" dependencies = [ - "indexmap 2.1.0", - "itoa", - "ryu", + "base64 0.13.1", + "hex", "serde", - "unsafe-libyaml", + "serde_with_macros", ] [[package]] -name = "sha-1" -version = "0.9.8" +name = "serde_with_macros" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "darling", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.6.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", ] [[package]] @@ -4102,19 +4455,22 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] [[package]] name = "sha2" -version = "0.10.6" -source = "git+https://github.com/RustCrypto/hashes.git?rev=1731ced4a116d61ba9dc6ee6d0f38fb8102e357a#1731ced4a116d61ba9dc6ee6d0f38fb8102e357a" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "cfg-if 1.0.0", + "block-buffer 0.9.0", + "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest 0.9.0", + "opaque-debug", ] [[package]] @@ -4123,18 +4479,32 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] [[package]] -name = "sha3" +name = "sha2_ce" version = "0.10.6" -source = "git+https://github.com/RustCrypto/hashes.git?rev=7a187e934c1f6c68e4b4e5cf37541b7a0d64d303#7a187e934c1f6c68e4b4e5cf37541b7a0d64d303" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca2daa77078f4ddff27e75c4bf59e4c2697525f56dbb3c842d34a5d1f2b04a2" dependencies = [ + "cfg-if", + "cpufeatures", "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", "keccak", + "opaque-debug", ] [[package]] @@ -4147,6 +4517,16 @@ dependencies = [ "keccak", ] +[[package]] +name = "sha3_ce" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34c9a08202c50378d8a07a5f458193a5f542d2828ac6640263dbc0c2533ea25e" +dependencies = [ + "digest 0.10.7", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -4158,15 +4538,15 @@ dependencies = [ [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -4193,9 +4573,21 @@ dependencies = [ [[package]] name = "simdutf8" -version = "0.1.4" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "simple_asn1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "thiserror", + "time", +] [[package]] name = "skeptic" @@ -4223,54 +4615,23 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" dependencies = [ "serde", ] [[package]] name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "soketto" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" -dependencies = [ - "base64 0.13.1", - "bytes", - "futures", - "httparse", - "log", - "rand 0.8.5", - "sha-1", + "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -4297,25 +4658,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.8", + "der 0.7.9", ] +[[package]] +name = "splitmut" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85070f382340e8b23a75808e83573ddf65f9ad9143df9573ca37c1ed2ee956a" + [[package]] name = "sqlformat" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" dependencies = [ - "itertools 0.12.0", "nom", "unicode_categories", ] [[package]] name = "sqlx" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" +checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e" dependencies = [ "sqlx-core", "sqlx-macros", @@ -4326,19 +4692,17 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" +checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e" dependencies = [ - "ahash 0.8.6", "atoi", "bigdecimal", "byteorder", "bytes", "chrono", "crc", - "crossbeam-queue 0.3.8", - "dotenvy", + "crossbeam-queue", "either", "event-listener", "futures-channel", @@ -4346,9 +4710,10 @@ dependencies = [ "futures-intrusive", "futures-io", "futures-util", + "hashbrown 0.14.5", "hashlink", "hex", - "indexmap 2.1.0", + "indexmap 2.6.0", "ipnetwork", "log", "memchr", @@ -4371,31 +4736,30 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" +checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "sqlx-core", "sqlx-macros-core", - "syn 1.0.109", + "syn 2.0.79", ] [[package]] name = "sqlx-macros-core" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" +checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" dependencies = [ - "atomic-write-file", "dotenvy", "either", - "heck 0.4.1", + "heck", "hex", "once_cell", - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "serde", "serde_json", "sha2 0.10.8", @@ -4403,7 +4767,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 1.0.109", + "syn 2.0.79", "tempfile", "tokio", "url", @@ -4411,14 +4775,14 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" +checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a" dependencies = [ "atoi", - "base64 0.21.5", + "base64 0.22.1", "bigdecimal", - "bitflags 2.4.1", + "bitflags 2.6.0", "byteorder", "bytes", "chrono", @@ -4456,14 +4820,14 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" +checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8" dependencies = [ "atoi", - "base64 0.21.5", + "base64 0.22.1", "bigdecimal", - "bitflags 2.4.1", + "bitflags 2.6.0", "byteorder", "chrono", "crc", @@ -4482,13 +4846,12 @@ dependencies = [ "log", "md-5", "memchr", - "num-bigint", + "num-bigint 0.4.6", "once_cell", "rand 0.8.5", "rust_decimal", "serde", "serde_json", - "sha1", "sha2 0.10.8", "smallvec", "sqlx-core", @@ -4500,9 +4863,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" +checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" dependencies = [ "atoi", "chrono", @@ -4516,10 +4879,10 @@ dependencies = [ "log", "percent-encoding", "serde", + "serde_urlencoded", "sqlx-core", "tracing", "url", - "urlencoding", ] [[package]] @@ -4536,42 +4899,59 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" -version = "0.24.1" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.24.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", + "heck", + "proc-macro2 1.0.87", + "quote 1.0.37", "rustversion", - "syn 1.0.109", + "syn 2.0.79", ] [[package]] name = "subtle" -version = "2.4.1" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] [[package]] name = "syn" @@ -4579,19 +4959,19 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.40" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "unicode-ident", ] @@ -4602,9 +4982,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" dependencies = [ "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -4613,6 +4993,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -4621,7 +5010,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys 0.6.0", ] [[package]] @@ -4634,6 +5034,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tagptr" version = "0.2.0" @@ -4648,15 +5058,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.1" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", - "redox_syscall", + "once_cell", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -4665,46 +5075,46 @@ version = "0.1.0" dependencies = [ "colored", "hex", - "multivm", "once_cell", "serde", "serde_json", "tracing", "tracing-subscriber", - "vlog", "zksync_contracts", + "zksync_multivm", "zksync_state", "zksync_types", "zksync_utils", + "zksync_vlog", ] [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", ] @@ -4719,12 +5129,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -4739,10 +5150,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -4766,9 +5178,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -4781,42 +5193,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -4831,19 +5232,20 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ "rustls", + "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -4852,24 +5254,22 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", - "futures-io", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" @@ -4877,45 +5277,47 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.6.0", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.6.0", "toml_datetime", - "winnow", + "winnow 0.6.20", ] [[package]] name = "tonic" -version = "0.9.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ + "async-stream", "async-trait", "axum", - "base64 0.21.5", + "base64 0.22.1", "bytes", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", - "prost 0.11.9", + "prost 0.13.3", + "socket2", "tokio", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -4941,17 +5343,31 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -4971,9 +5387,9 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -4986,17 +5402,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-log" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -5010,18 +5415,20 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.21.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75327c6b667828ddc28f5e3f169036cb793c3f588d83bf0f262a7f062ffed3c8" +checksum = "a9784ed4da7d921bc8df6963f8c80a0e4ce34ba6ba76668acadd3edbd985ff3b" dependencies = [ + "js-sys", "once_cell", "opentelemetry", "opentelemetry_sdk", "smallvec", "tracing", "tracing-core", - "tracing-log 0.1.4", + "tracing-log", "tracing-subscriber", + "web-time", ] [[package]] @@ -5052,15 +5459,15 @@ dependencies = [ "time", "tracing", "tracing-core", - "tracing-log 0.2.0", + "tracing-log", "tracing-serde", ] [[package]] name = "triomphe" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" +checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" [[package]] name = "try-lock" @@ -5068,12 +5475,24 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typemap_rev" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74b08b0c1257381af16a5c3605254d529d3e7e109f3c62befc5d168968192998" + [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "uint" version = "0.9.5" @@ -5106,42 +5525,54 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "unicode-xid" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unicode_categories" @@ -5155,7 +5586,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ad948c1cb799b1a70f836077721a92a35ac177d4daddf4c20a633786d4cf618" dependencies = [ - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -5173,11 +5604,11 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" dependencies = [ - "base64 0.21.5", + "base64 0.22.1", "log", "native-tls", "once_cell", @@ -5186,12 +5617,12 @@ dependencies = [ [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna", "percent-encoding", "serde", ] @@ -5204,9 +5635,9 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "uuid" -version = "1.6.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "serde", ] @@ -5225,54 +5656,53 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vise" -version = "0.1.0" -source = "git+https://github.com/matter-labs/vise.git?rev=a5bb80c9ce7168663114ee30e794d6dc32159ee4#a5bb80c9ce7168663114ee30e794d6dc32159ee4" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ade36f3548b1524396f4de7b36f4f210c8a01dfab568eb2bff466af64eb6e5" dependencies = [ "compile-fmt", + "ctor", "elsa", - "linkme", "once_cell", "prometheus-client", "vise-macros", ] [[package]] -name = "vise-macros" -version = "0.1.0" -source = "git+https://github.com/matter-labs/vise.git?rev=a5bb80c9ce7168663114ee30e794d6dc32159ee4#a5bb80c9ce7168663114ee30e794d6dc32159ee4" +name = "vise-exporter" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671d3b894d5d0849f0a597f56bf071f42d4f2a1cbcf2f78ca21f870ab7c0cc2b" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "hyper 0.14.30", + "once_cell", + "tokio", + "tracing", + "vise", ] [[package]] -name = "vlog" -version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +name = "vise-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a511871dc5de990a3b2a0e715facfbc5da848c0c0395597a1415029fb7c250a" dependencies = [ - "chrono", - "opentelemetry", - "opentelemetry-otlp", - "opentelemetry-semantic-conventions", - "sentry", - "serde_json", - "tracing", - "tracing-opentelemetry", - "tracing-subscriber", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -5293,38 +5723,45 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -5332,115 +5769,76 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ - "quote", + "quote 1.0.37", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] -name = "web-sys" -version = "0.3.66" +name = "wasm-streams" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" dependencies = [ + "futures-util", "js-sys", "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] -name = "web3" -version = "0.19.0" +name = "web-sys" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5388522c899d1e1c96a4c307e3797e0f697ba7c77dd8e0e625ecba9dd0342937" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ - "arrayvec 0.7.4", - "base64 0.21.5", - "bytes", - "derive_more 0.99.17", - "ethabi", - "ethereum-types", - "futures", - "futures-timer", - "headers", - "hex", - "idna 0.4.0", - "jsonrpc-core", - "log", - "once_cell", - "parking_lot", - "pin-project", - "reqwest", - "rlp", - "secp256k1", - "serde", - "serde_json", - "soketto", - "tiny-keccak 2.0.2", - "tokio", - "tokio-stream", - "tokio-util", - "url", - "web3-async-native-tls", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "web3-async-native-tls" -version = "0.4.0" +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6d8d1636b2627fe63518d5a9b38a569405d9c9bc665c43c9c341de57227ebb" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ - "native-tls", - "thiserror", - "tokio", - "url", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "webpki-roots" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" - -[[package]] -name = "which" -version = "4.4.2" +name = "whoami" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" dependencies = [ - "either", - "home", - "once_cell", - "rustix", + "redox_syscall", + "wasite", ] -[[package]] -name = "whoami" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" - [[package]] name = "winapi" version = "0.3.9" @@ -5459,11 +5857,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -5474,11 +5872,41 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -5496,7 +5924,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -5516,17 +5953,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -5537,9 +5975,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -5549,9 +5987,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -5561,9 +5999,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -5573,9 +6017,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -5585,9 +6029,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -5597,9 +6041,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -5609,15 +6053,24 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] [[package]] name = "winnow" -version = "0.5.26" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67b5f0a4e7a27a64c651977932b9dc5667ca7fc31ac44b03ed37a0cf42fdfff" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -5628,7 +6081,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "windows-sys 0.48.0", ] @@ -5642,30 +6095,37 @@ dependencies = [ ] [[package]] -name = "zerocopy" -version = "0.7.30" +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306dca4455518f1f31635ec308b6b3e4eb1b11758cefafc782827d0aa7acb5c7" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.30" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be912bf68235a88fbefd1b73415cb218405958d1655b2ece9035a19920bdf6ba" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -5676,47 +6136,34 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "zk_evm" -version = "1.3.1" -source = "git+https://github.com/matter-labs/era-zk_evm.git?tag=v1.3.1-rc2#0a7c775932db4839ff6b7fb0db9bdb3583ab54c0" +version = "0.131.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b83ee7887fb29fda57c6b26a0f64c9b211459d718f8a26310f962e69f0b764" dependencies = [ - "blake2 0.10.6 (git+https://github.com/RustCrypto/hashes.git?rev=1f727ce37ff40fa0cce84eb8543a45bdd3ca4a4e)", + "blake2_ce", "k256 0.11.6", "lazy_static", "num", "serde", "serde_json", - "sha2 0.10.6", - "sha3 0.10.6", - "static_assertions", - "zkevm_opcode_defs 1.3.1", -] - -[[package]] -name = "zk_evm" -version = "1.3.3" -source = "git+https://github.com/matter-labs/era-zk_evm.git?tag=v1.3.3-rc2#fbee20f5bac7d6ca3e22ae69b2077c510a07de4e" -dependencies = [ - "anyhow", - "lazy_static", - "num", - "serde", - "serde_json", + "sha2_ce", + "sha3_ce", "static_assertions", - "zk_evm_abstractions 0.1.0", - "zkevm_opcode_defs 1.3.2", + "zkevm_opcode_defs 0.131.0", ] [[package]] name = "zk_evm" -version = "1.3.3" -source = "git+https://github.com/matter-labs/era-zk_evm.git?branch=v1.3.3#fbee20f5bac7d6ca3e22ae69b2077c510a07de4e" +version = "0.133.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9af08e9284686a1b0c89ec4931eb915ac0729367f1247abd06164874fe738106" dependencies = [ "anyhow", "lazy_static", @@ -5724,14 +6171,15 @@ dependencies = [ "serde", "serde_json", "static_assertions", - "zk_evm_abstractions 0.1.0", - "zkevm_opcode_defs 1.3.2", + "zk_evm_abstractions 0.140.0", + "zkevm_opcode_defs 0.132.0", ] [[package]] name = "zk_evm" -version = "1.4.0" -source = "git+https://github.com/matter-labs/era-zk_evm.git?branch=v1.4.0#dd76fc5badf2c05278a21b38015a7798fe2fe358" +version = "0.140.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349bb8320d12578537658792df708f43c52e6330f0df071f812cb93b04ade962" dependencies = [ "anyhow", "lazy_static", @@ -5739,14 +6187,15 @@ dependencies = [ "serde", "serde_json", "static_assertions", - "zk_evm_abstractions 0.1.0", - "zkevm_opcode_defs 1.3.2", + "zk_evm_abstractions 0.140.0", + "zkevm_opcode_defs 0.132.0", ] [[package]] name = "zk_evm" -version = "1.4.1" -source = "git+https://github.com/matter-labs/era-zk_evm.git?branch=v1.4.1#6250dbf64b2d14ced87a127735da559f27a432d5" +version = "0.141.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8886ba5989b952b7b76096469eeb6fdfaf3369770e9e22a6f67dc4b7d65f9243" dependencies = [ "anyhow", "lazy_static", @@ -5754,14 +6203,15 @@ dependencies = [ "serde", "serde_json", "static_assertions", - "zk_evm_abstractions 1.4.1", - "zkevm_opcode_defs 1.4.1", + "zk_evm_abstractions 0.141.0", + "zkevm_opcode_defs 0.141.0", ] [[package]] name = "zk_evm" -version = "1.5.0" -source = "git+https://github.com/matter-labs/era-zk_evm.git?branch=v1.5.0#0448e26ffd8e2f1935ff8cd3303fe5a504cd5d7b" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6e69931f24db5cf333b714721e8d80ff88bfdb7da8c3dc7882612ffddb8d27" dependencies = [ "anyhow", "lazy_static", @@ -5769,54 +6219,57 @@ dependencies = [ "serde", "serde_json", "static_assertions", - "zk_evm_abstractions 1.5.0", + "zk_evm_abstractions 0.150.5", ] [[package]] name = "zk_evm_abstractions" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-zk_evm_abstractions.git#32dd320953841aa78579d9da08abbc70bcaed175" +version = "0.140.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be696258861eba4e6625a5665084b2266720bb67f4ba69819469700ac5c6a401" dependencies = [ "anyhow", "num_enum 0.6.1", "serde", "static_assertions", - "zkevm_opcode_defs 1.3.2", + "zkevm_opcode_defs 0.132.0", ] [[package]] name = "zk_evm_abstractions" -version = "1.4.1" -source = "git+https://github.com/matter-labs/era-zk_evm_abstractions.git?branch=v1.4.1#0aac08c3b097ee8147e748475117ac46bddcdcef" +version = "0.141.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637a3cb6cb475bb238bee3e450763205d36fe6c92dc1b23300655927915baf03" dependencies = [ "anyhow", "num_enum 0.6.1", "serde", "static_assertions", - "zkevm_opcode_defs 1.4.1", + "zkevm_opcode_defs 0.141.0", ] [[package]] name = "zk_evm_abstractions" -version = "1.5.0" -source = "git+https://github.com/matter-labs/era-zk_evm_abstractions.git?branch=v1.5.0#e464b2cf2b146d883be80e7d690c752bf670ff05" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6b0720261ab55490fe3a96e96de30d5d7b277940b52ea7f52dbf564eb1748" dependencies = [ "anyhow", "num_enum 0.6.1", "serde", "static_assertions", - "zkevm_opcode_defs 1.5.0", + "zkevm_opcode_defs 0.150.5", ] [[package]] name = "zkevm_circuits" -version = "1.4.0" -source = "git+https://github.com/matter-labs/era-zkevm_circuits.git?branch=v1.4.0#fb3e2574b5c890342518fc930c145443f039a105" +version = "0.140.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c365c801e0c6eda83fbd153df45575172beb406bfb663d386f9154b4325eda" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bincode", "boojum", - "cs_derive", "derivative", "hex", "itertools 0.10.5", @@ -5826,18 +6279,19 @@ dependencies = [ "serde", "serde_json", "smallvec", - "zkevm_opcode_defs 1.3.2", + "zkevm_opcode_defs 0.132.0", + "zksync_cs_derive", ] [[package]] name = "zkevm_circuits" -version = "1.4.1" -source = "git+https://github.com/matter-labs/era-zkevm_circuits.git?branch=v1.4.1#8bf24543ffc5bafab34182388394e887ecb37d17" +version = "0.141.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ccd0352e122a4e6f0046d2163b7e692e627b23fc3264faa77331a21b65833fd" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bincode", "boojum", - "cs_derive", "derivative", "hex", "itertools 0.10.5", @@ -5847,17 +6301,18 @@ dependencies = [ "serde", "serde_json", "smallvec", - "zkevm_opcode_defs 1.4.1", + "zkevm_opcode_defs 0.141.0", + "zksync_cs_derive", ] [[package]] name = "zkevm_circuits" -version = "1.5.0" -source = "git+https://github.com/matter-labs/era-zkevm_circuits.git?branch=v1.5.0#861f81029bf3a916dae55afa5bd7f82b2eaca98b" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784fa7cfb51e17c5ced112bca43da30b3468b2347b7af0427ad9638759fb140e" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "boojum", - "cs_derive", "derivative", "hex", "itertools 0.10.5", @@ -5866,13 +6321,15 @@ dependencies = [ "seq-macro", "serde", "smallvec", - "zkevm_opcode_defs 1.5.0", + "zkevm_opcode_defs 0.150.5", + "zksync_cs_derive", ] [[package]] name = "zkevm_opcode_defs" -version = "1.3.1" -source = "git+https://github.com/matter-labs/era-zkevm_opcode_defs.git?branch=v1.3.1#00d4ad2292bd55374a0fa10fe11686d7a109d8a0" +version = "0.131.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e0154bd4ae8202c96c52b29dd44f944bfd08c1c233fef843744463964de957" dependencies = [ "bitflags 1.3.2", "ethereum-types", @@ -5882,27 +6339,29 @@ dependencies = [ [[package]] name = "zkevm_opcode_defs" -version = "1.3.2" -source = "git+https://github.com/matter-labs/era-zkevm_opcode_defs.git?branch=v1.3.2#dffacadeccdfdbff4bc124d44c595c4a6eae5013" +version = "0.132.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0769f7b27d8fb06e715da3290c575cac5d04d10a557faef180e847afce50ac4" dependencies = [ - "bitflags 2.4.1", - "blake2 0.10.6 (git+https://github.com/RustCrypto/hashes.git?rev=1f727ce37ff40fa0cce84eb8543a45bdd3ca4a4e)", + "bitflags 2.6.0", + "blake2 0.10.6", "ethereum-types", "k256 0.11.6", "lazy_static", - "sha2 0.10.6", - "sha3 0.10.6", + "sha2_ce", + "sha3_ce", ] [[package]] name = "zkevm_opcode_defs" -version = "1.4.1" -source = "git+https://github.com/matter-labs/era-zkevm_opcode_defs.git?branch=v1.4.1#ba8228ff0582d21f64d6a319d50d0aec48e9e7b6" +version = "0.141.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6be7bd5f0e0b61211f544147289640b4712715589d7f2fe5229d92a7a3ac64c0" dependencies = [ - "bitflags 2.4.1", - "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.6.0", + "blake2 0.10.6", "ethereum-types", - "k256 0.13.3", + "k256 0.13.4", "lazy_static", "sha2 0.10.8", "sha3 0.10.8", @@ -5910,13 +6369,14 @@ dependencies = [ [[package]] name = "zkevm_opcode_defs" -version = "1.5.0" -source = "git+https://github.com/matter-labs/era-zkevm_opcode_defs.git?branch=v1.5.0#109d9f734804a8b9dc0531c0b576e2a0f55a40de" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79055eae1b6c1ab80793ed9d77d2964c9c896afa4b5dfed278cf58cd10acfe8f" dependencies = [ - "bitflags 2.4.1", - "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.6.0", + "blake2 0.10.6", "ethereum-types", - "k256 0.13.3", + "k256 0.13.4", "lazy_static", "p256", "serde", @@ -5927,20 +6387,51 @@ dependencies = [ [[package]] name = "zksync_basic_types" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ + "anyhow", "chrono", - "num_enum 0.7.2", + "ethabi", + "hex", + "num_enum 0.7.3", + "secrecy", "serde", "serde_json", + "serde_with", "strum", - "web3", + "thiserror", + "tiny-keccak 2.0.2", + "url", +] + +[[package]] +name = "zksync_bellman" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffa03efe9bdb137a4b36b97d1a74237e18c9ae42b755163d903a9d48c1a5d80" +dependencies = [ + "arrayvec 0.7.6", + "bit-vec", + "blake2s_simd", + "byteorder", + "cfg-if", + "crossbeam", + "futures", + "hex", + "lazy_static", + "num_cpus", + "rand 0.4.6", + "serde", + "smallvec", + "tiny-keccak 1.5.0", + "zksync_pairing", ] [[package]] name = "zksync_concurrency" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "035269d811b3770debca372141ab64cad067dce8e58cb39a48cb7617d30c626b" dependencies = [ "anyhow", "once_cell", @@ -5958,43 +6449,55 @@ dependencies = [ [[package]] name = "zksync_config" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", "rand 0.8.5", + "secrecy", "serde", + "strum", + "strum_macros", + "time", + "url", + "vise", "zksync_basic_types", + "zksync_concurrency", "zksync_consensus_utils", "zksync_crypto_primitives", ] [[package]] name = "zksync_consensus_crypto" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e38d1b5ed28c66e785caff53ea4863375555d818aafa03290397192dd3e665" dependencies = [ "anyhow", "blst", "ed25519-dalek", - "ff_ce", + "elliptic-curve 0.13.8", "hex", - "pairing_ce 0.28.5 (git+https://github.com/matter-labs/pairing.git?rev=d24f2c5871089c4cd4f54c0ca266bb9fef6115eb)", - "rand 0.4.6", + "k256 0.13.4", + "num-bigint 0.4.6", + "num-traits", "rand 0.8.5", "sha3 0.10.8", "thiserror", "tracing", + "zeroize", ] [[package]] name = "zksync_consensus_roles" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e49fbd4e69b276058f3dfc06cf6ada0e8caa6ed826e81289e4d596da95a0f17a" dependencies = [ "anyhow", "bit-vec", "hex", - "prost 0.12.3", + "num-bigint 0.4.6", + "prost 0.12.6", "rand 0.8.5", "serde", "thiserror", @@ -6008,17 +6511,19 @@ dependencies = [ [[package]] name = "zksync_consensus_storage" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b2aab4ed18b13cd584f4edcc2546c8da82f89ac62e525063e12935ff28c9be" dependencies = [ "anyhow", "async-trait", - "prost 0.12.3", + "prost 0.12.6", "rand 0.8.5", "thiserror", "tracing", "vise", "zksync_concurrency", + "zksync_consensus_crypto", "zksync_consensus_roles", "zksync_protobuf", "zksync_protobuf_build", @@ -6026,9 +6531,11 @@ dependencies = [ [[package]] name = "zksync_consensus_utils" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10bac8f471b182d4fa3d40cf158aac3624fe636a1ff0b4cf3fe26a0e20c68a42" dependencies = [ + "anyhow", "rand 0.8.5", "thiserror", "zksync_concurrency", @@ -6037,7 +6544,7 @@ dependencies = [ [[package]] name = "zksync_contracts" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "envy", "ethabi", @@ -6048,40 +6555,40 @@ dependencies = [ "zksync_utils", ] -[[package]] -name = "zksync_crypto" -version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" -dependencies = [ - "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hex", - "once_cell", - "serde", - "sha2 0.10.8", - "thiserror", - "zksync_basic_types", -] - [[package]] name = "zksync_crypto_primitives" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", + "blake2 0.10.6", "hex", + "rand 0.8.5", "secp256k1", "serde", "serde_json", + "sha2 0.10.8", "thiserror", - "web3", "zksync_basic_types", "zksync_utils", ] +[[package]] +name = "zksync_cs_derive" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5939e2df4288c263c706ff18ac718e984149223ad4289d6d957d767dcfc04c81" +dependencies = [ + "proc-macro-error", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 1.0.109", +] + [[package]] name = "zksync_dal" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", "bigdecimal", @@ -6089,7 +6596,7 @@ dependencies = [ "chrono", "hex", "itertools 0.10.5", - "prost 0.12.3", + "prost 0.12.6", "rand 0.8.5", "serde", "serde_json", @@ -6099,21 +6606,26 @@ dependencies = [ "tokio", "tracing", "vise", + "zksync_concurrency", + "zksync_consensus_crypto", "zksync_consensus_roles", "zksync_consensus_storage", + "zksync_consensus_utils", "zksync_contracts", "zksync_db_connection", + "zksync_l1_contract_interface", "zksync_protobuf", "zksync_protobuf_build", "zksync_system_constants", "zksync_types", "zksync_utils", + "zksync_vm_interface", ] [[package]] name = "zksync_db_connection" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", "rand 0.8.5", @@ -6123,45 +6635,159 @@ dependencies = [ "thiserror", "tokio", "tracing", - "url", "vise", - "zksync_health_check", + "zksync_basic_types", ] [[package]] -name = "zksync_health_check" -version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +name = "zksync_ff" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9524b06780b5e164e84b38840c7c428c739f051f35af6efc4d1285f629ceb88e" dependencies = [ - "async-trait", - "futures", + "byteorder", + "hex", + "rand 0.4.6", + "serde", + "zksync_ff_derive", +] + +[[package]] +name = "zksync_ff_derive" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f91e58e75d65877f09f83bc3dca8f054847ae7ec4f3e64bfa610a557edd8e8e" +dependencies = [ + "num-bigint 0.4.6", + "num-integer", + "num-traits", + "proc-macro2 1.0.87", + "quote 1.0.37", + "serde", + "syn 1.0.109", +] + +[[package]] +name = "zksync_kzg" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb8a9c76c172a6d639855ee342b9a670e3ba472f5ae302f771b1c3ee777dc88" +dependencies = [ + "boojum", + "derivative", + "hex", + "once_cell", + "rayon", "serde", "serde_json", - "thiserror", - "tokio", - "tracing", - "vise", + "serde_with", + "zkevm_circuits 0.150.5", +] + +[[package]] +name = "zksync_l1_contract_interface" +version = "0.1.0" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "anyhow", + "hex", + "once_cell", + "sha2 0.10.8", + "sha3 0.10.8", + "zksync_kzg", + "zksync_prover_interface", + "zksync_solidity_vk_codegen", + "zksync_types", ] [[package]] name = "zksync_mini_merkle_tree" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "once_cell", "zksync_basic_types", - "zksync_crypto", + "zksync_crypto_primitives", ] [[package]] -name = "zksync_protobuf" +name = "zksync_multivm" +version = "0.1.0" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "anyhow", + "circuit_sequencer_api 0.133.1", + "circuit_sequencer_api 0.140.3", + "circuit_sequencer_api 0.141.2", + "circuit_sequencer_api 0.142.2", + "circuit_sequencer_api 0.150.5", + "ethabi", + "hex", + "itertools 0.10.5", + "once_cell", + "thiserror", + "tracing", + "vise", + "zk_evm 0.131.0-rc.2", + "zk_evm 0.133.0", + "zk_evm 0.140.0", + "zk_evm 0.141.0", + "zk_evm 0.150.5", + "zksync_contracts", + "zksync_system_constants", + "zksync_types", + "zksync_utils", + "zksync_vm2", + "zksync_vm_interface", +] + +[[package]] +name = "zksync_object_store" version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "flate2", + "google-cloud-auth", + "google-cloud-storage", + "http 1.1.0", + "prost 0.12.6", + "rand 0.8.5", + "reqwest 0.12.8", + "serde_json", + "tokio", + "tracing", + "vise", + "zksync_config", + "zksync_protobuf", + "zksync_types", +] + +[[package]] +name = "zksync_pairing" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8412ae5574472fa567a097e183f9a01974b99dd0b5da3bfa1bbe6c57c579aa2" +dependencies = [ + "byteorder", + "cfg-if", + "rand 0.4.6", + "serde", + "zksync_ff", +] + +[[package]] +name = "zksync_protobuf" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abd55c64f54cb10967a435422f66ff5880ae14a232b245517c7ce38da32e0cab" dependencies = [ "anyhow", "bit-vec", "once_cell", - "prost 0.12.3", + "prost 0.12.6", "prost-reflect", "quick-protobuf", "rand 0.8.5", @@ -6175,37 +6801,73 @@ dependencies = [ [[package]] name = "zksync_protobuf_build" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4121952bcaf711005dd554612fc6e2de9b30cb58088508df87f1d38046ce8ac8" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "prettyplease", - "proc-macro2", + "proc-macro2 1.0.87", "prost-build", "prost-reflect", "protox", - "quote", - "syn 2.0.40", + "quote 1.0.37", + "syn 2.0.79", +] + +[[package]] +name = "zksync_prover_interface" +version = "0.1.0" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "chrono", + "circuit_sequencer_api 0.150.5", + "serde", + "serde_with", + "strum", + "zksync_multivm", + "zksync_object_store", + "zksync_types", ] [[package]] name = "zksync_shared_metrics" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ + "rustc_version", + "tracing", "vise", "zksync_dal", "zksync_types", ] +[[package]] +name = "zksync_solidity_vk_codegen" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b310ab8a21681270e73f177ddf7974cabb7a96f0624ab8b008fd6ee1f9b4f687" +dependencies = [ + "ethereum-types", + "franklin-crypto", + "handlebars", + "hex", + "paste", + "rescue_poseidon", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "zksync_state" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", "async-trait", + "backon", "chrono", "itertools 0.10.5", "mini-moka", @@ -6218,12 +6880,13 @@ dependencies = [ "zksync_storage", "zksync_types", "zksync_utils", + "zksync_vm_interface", ] [[package]] name = "zksync_storage" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "num_cpus", "once_cell", @@ -6236,7 +6899,7 @@ dependencies = [ [[package]] name = "zksync_system_constants" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "once_cell", "zksync_basic_types", @@ -6246,24 +6909,27 @@ dependencies = [ [[package]] name = "zksync_types" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", - "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bigdecimal", + "blake2 0.10.6", "chrono", - "derive_more 1.0.0-beta.6", + "derive_more", "hex", "itertools 0.10.5", "num", - "num_enum 0.7.2", + "num_enum 0.7.3", "once_cell", - "prost 0.12.3", + "prost 0.12.6", "rlp", "secp256k1", "serde", "serde_json", + "serde_with", "strum", "thiserror", + "tracing", "zksync_basic_types", "zksync_config", "zksync_contracts", @@ -6278,29 +6944,93 @@ dependencies = [ [[package]] name = "zksync_utils" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", "bigdecimal", "futures", "hex", - "itertools 0.10.5", "num", - "reqwest", + "once_cell", + "reqwest 0.12.8", "serde", + "serde_json", "thiserror", "tokio", "tracing", - "vlog", - "zk_evm 1.3.3 (git+https://github.com/matter-labs/era-zk_evm.git?tag=v1.3.3-rc2)", + "zk_evm 0.133.0", "zksync_basic_types", + "zksync_vlog", +] + +[[package]] +name = "zksync_vlog" +version = "0.1.0" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "anyhow", + "chrono", + "opentelemetry", + "opentelemetry-appender-tracing", + "opentelemetry-otlp", + "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "sentry", + "serde", + "serde_json", + "thiserror", + "time", + "tokio", + "tracing", + "tracing-opentelemetry", + "tracing-subscriber", + "url", + "vise", + "vise-exporter", +] + +[[package]] +name = "zksync_vm2" +version = "0.2.1" +source = "git+https://github.com/matter-labs/vm2.git?rev=a233d44bbe61dc6a758a754c3b78fe4f83e56699#a233d44bbe61dc6a758a754c3b78fe4f83e56699" +dependencies = [ + "enum_dispatch", + "primitive-types", + "zk_evm_abstractions 0.150.5", + "zkevm_opcode_defs 0.150.5", + "zksync_vm2_interface", +] + +[[package]] +name = "zksync_vm2_interface" +version = "0.2.1" +source = "git+https://github.com/matter-labs/vm2.git?rev=a233d44bbe61dc6a758a754c3b78fe4f83e56699#a233d44bbe61dc6a758a754c3b78fe4f83e56699" +dependencies = [ + "primitive-types", +] + +[[package]] +name = "zksync_vm_interface" +version = "0.1.0" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "anyhow", + "async-trait", + "hex", + "pretty_assertions", + "serde", + "thiserror", + "tracing", + "zksync_contracts", + "zksync_system_constants", + "zksync_types", ] [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/system-contracts/bootloader/test_infra/Cargo.toml b/system-contracts/bootloader/test_infra/Cargo.toml index cfcd2c9a3..8ca71ef8a 100644 --- a/system-contracts/bootloader/test_infra/Cargo.toml +++ b/system-contracts/bootloader/test_infra/Cargo.toml @@ -7,12 +7,12 @@ edition = "2021" [dependencies] -multivm = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } -zksync_types = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } -zksync_contracts = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } -zksync_utils = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } -zksync_state = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } -vlog = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } +zksync_multivm = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } +zksync_types = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } +zksync_contracts = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } +zksync_utils = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } +zksync_state = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } +zksync_vlog = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } colored = "2.0" hex = "0.4" diff --git a/system-contracts/bootloader/test_infra/rust-toolchain b/system-contracts/bootloader/test_infra/rust-toolchain index 9a87fb21c..226a309c8 100644 --- a/system-contracts/bootloader/test_infra/rust-toolchain +++ b/system-contracts/bootloader/test_infra/rust-toolchain @@ -1 +1 @@ -nightly-2023-08-21 +nightly-2024-08-01 \ No newline at end of file diff --git a/system-contracts/bootloader/test_infra/src/hook.rs b/system-contracts/bootloader/test_infra/src/hook.rs index 04bacc90c..b1f0f1078 100644 --- a/system-contracts/bootloader/test_infra/src/hook.rs +++ b/system-contracts/bootloader/test_infra/src/hook.rs @@ -1,9 +1,9 @@ -use multivm::vm_latest::{ - constants::{BOOTLOADER_HEAP_PAGE, get_vm_hook_start_position_latest}, +use zksync_multivm::vm_latest::{ + constants::{get_vm_hook_start_position_latest, BOOTLOADER_HEAP_PAGE}, HistoryMode, SimpleMemory, }; -use multivm::zk_evm_latest::{ +use zksync_multivm::zk_evm_latest::{ aux_structures::MemoryPage, tracing::{BeforeExecutionData, VmLocalStateData}, zkevm_opcode_defs::{FatPointer, Opcode, UMAOpcode}, diff --git a/system-contracts/bootloader/test_infra/src/main.rs b/system-contracts/bootloader/test_infra/src/main.rs index 3928200e4..4e55b0ed3 100644 --- a/system-contracts/bootloader/test_infra/src/main.rs +++ b/system-contracts/bootloader/test_infra/src/main.rs @@ -1,25 +1,25 @@ use crate::{test_count_tracer::TestCountTracer, tracer::BootloaderTestTracer}; use colored::Colorize; -use multivm::interface::{ - L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode, VmExecutionMode, VmInterface, -}; -use multivm::vm_latest::{HistoryDisabled, ToTracerPointer, Vm}; use once_cell::sync::OnceCell; -use zksync_types::fee_model::BatchFeeInput; use std::process; +use zksync_multivm::interface::{ + L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode, VmExecutionMode, VmFactory, VmInterface, +}; +use zksync_multivm::vm_latest::{HistoryDisabled, ToTracerPointer, TracerDispatcher, Vm}; +use zksync_state::interface::{ + InMemoryStorage, StoragePtr, StorageView, IN_MEMORY_STORAGE_DEFAULT_NETWORK_ID, +}; +use zksync_types::fee_model::BatchFeeInput; -use multivm::interface::{ExecutionResult, Halt}; use std::{env, sync::Arc}; use tracing_subscriber::fmt; use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use zksync_contracts::{ - read_zbin_bytecode, BaseSystemContracts, ContractLanguage, SystemContractCode, + read_yul_bytecode, BaseSystemContracts, ContractLanguage, SystemContractCode, SystemContractsRepo, }; -use zksync_state::{ - InMemoryStorage, StoragePtr, StorageView, IN_MEMORY_STORAGE_DEFAULT_NETWORK_ID, -}; +use zksync_multivm::interface::{ExecutionResult, Halt}; use zksync_types::system_contracts::get_system_smart_contracts_from_dir; use zksync_types::{block::L2BlockHasher, Address, L1BatchNumber, L2BlockNumber, U256}; use zksync_types::{L2ChainId, Transaction}; @@ -32,11 +32,13 @@ mod tracer; // Executes bootloader unittests. fn execute_internal_bootloader_test() { - let test_location = env::current_dir() - .unwrap() - .join("../build/artifacts/bootloader_test.yul.zbin"); - println!("Current dir is {:?}", test_location); - let bytecode = read_zbin_bytecode(test_location.as_path()); + let artifacts_location_path = env::current_dir().unwrap().join("../build/artifacts"); + let artifacts_location = artifacts_location_path + .to_str() + .expect("Invalid path: {artifacts_location_path:?}"); + println!("Current dir is {:?}", artifacts_location); + + let bytecode = read_yul_bytecode(artifacts_location, "bootloader_test"); let hash = hash_bytecode(&bytecode); let bootloader = SystemContractCode { code: bytes_to_be_words(bytecode), @@ -57,6 +59,7 @@ fn execute_internal_bootloader_test() { let base_system_contract = BaseSystemContracts { bootloader, default_aa, + evm_emulator: None, }; let system_env = SystemEnv { @@ -91,19 +94,23 @@ fn execute_internal_bootloader_test() { StorageView::new(InMemoryStorage::with_custom_system_contracts_and_chain_id( L2ChainId::from(IN_MEMORY_STORAGE_DEFAULT_NETWORK_ID), hash_bytecode, - get_system_smart_contracts_from_dir(env::current_dir().unwrap().join("../../")), + get_system_smart_contracts_from_dir( + env::current_dir().unwrap().join("../../"), + false, + ), )) .to_rc_ptr(); let mut vm: Vm<_, HistoryDisabled> = - Vm::new(l1_batch_env.clone(), system_env.clone(), storage.clone()); + VmFactory::new(l1_batch_env.clone(), system_env.clone(), storage.clone()); let test_count = Arc::new(OnceCell::default()); let custom_tracers = TestCountTracer::new(test_count.clone()).into_tracer_pointer(); // We're using a TestCountTracer (and passing 0 as fee account) - this should cause the bootloader // test framework to report number of tests via VM hook. - vm.inspect(custom_tracers.into(), VmExecutionMode::Bootloader); + let mut tracer_dispatcher = TracerDispatcher::from(custom_tracers); + vm.inspect(&mut tracer_dispatcher, VmExecutionMode::Bootloader); test_count.get().unwrap().clone() }; @@ -119,7 +126,10 @@ fn execute_internal_bootloader_test() { StorageView::new(InMemoryStorage::with_custom_system_contracts_and_chain_id( L2ChainId::from(IN_MEMORY_STORAGE_DEFAULT_NETWORK_ID), hash_bytecode, - get_system_smart_contracts_from_dir(env::current_dir().unwrap().join("../../")), + get_system_smart_contracts_from_dir( + env::current_dir().unwrap().join("../../"), + false, + ), )) .to_rc_ptr(); @@ -138,13 +148,16 @@ fn execute_internal_bootloader_test() { test_name.clone(), ) .into_tracer_pointer(); + let mut tracer_dispatcher = TracerDispatcher::from(custom_tracers); // Let's insert transactions into slots. They are not executed, but the tests can run functions against them. let json_str = include_str!("test_transactions/0.json"); let tx: Transaction = serde_json::from_str(json_str).unwrap(); vm.push_transaction(tx); - let result = vm.inspect(custom_tracers.into(), VmExecutionMode::Bootloader); + let result = vm.inspect(&mut tracer_dispatcher, VmExecutionMode::Bootloader); + drop(tracer_dispatcher); + let mut test_result = Arc::into_inner(test_result).unwrap().into_inner(); let requested_assert = Arc::into_inner(requested_assert).unwrap().into_inner(); let test_name = Arc::into_inner(test_name) diff --git a/system-contracts/bootloader/test_infra/src/test_count_tracer.rs b/system-contracts/bootloader/test_infra/src/test_count_tracer.rs index 1c2dfa523..f82a4df6a 100644 --- a/system-contracts/bootloader/test_infra/src/test_count_tracer.rs +++ b/system-contracts/bootloader/test_infra/src/test_count_tracer.rs @@ -1,10 +1,10 @@ use std::sync::Arc; -use multivm::interface::dyn_tracers::vm_1_5_0::DynTracer; -use multivm::vm_latest::{HistoryMode, SimpleMemory, VmTracer}; -use multivm::zk_evm_latest::tracing::{BeforeExecutionData, VmLocalStateData}; use once_cell::sync::OnceCell; -use zksync_state::{StoragePtr, WriteStorage}; +use zksync_multivm::tracers::dynamic::vm_1_5_0::DynTracer; +use zksync_multivm::vm_latest::{HistoryMode, SimpleMemory, VmTracer}; +use zksync_multivm::zk_evm_latest::tracing::{BeforeExecutionData, VmLocalStateData}; +use zksync_state::interface::{StoragePtr, WriteStorage}; use crate::hook::TestVmHook; diff --git a/system-contracts/bootloader/test_infra/src/tracer.rs b/system-contracts/bootloader/test_infra/src/tracer.rs index c38875235..8b26cba35 100644 --- a/system-contracts/bootloader/test_infra/src/tracer.rs +++ b/system-contracts/bootloader/test_infra/src/tracer.rs @@ -3,14 +3,15 @@ use std::sync::Arc; use colored::Colorize; use once_cell::sync::OnceCell; -use multivm::interface::{ - dyn_tracers::vm_1_5_0::DynTracer, - tracer::{TracerExecutionStatus, TracerExecutionStopReason}, +use zksync_multivm::tracers::dynamic::vm_1_5_0::DynTracer; + +use zksync_multivm::interface::tracer::{TracerExecutionStatus, TracerExecutionStopReason}; +use zksync_multivm::vm_latest::{ + BootloaderState, HistoryMode, SimpleMemory, VmTracer, ZkSyncVmState, }; -use multivm::vm_latest::{BootloaderState, HistoryMode, SimpleMemory, VmTracer, ZkSyncVmState}; -use multivm::zk_evm_latest::tracing::{BeforeExecutionData, VmLocalStateData}; +use zksync_multivm::zk_evm_latest::tracing::{BeforeExecutionData, VmLocalStateData}; -use zksync_state::{StoragePtr, WriteStorage}; +use zksync_state::interface::{StoragePtr, WriteStorage}; use crate::hook::TestVmHook; diff --git a/system-contracts/contracts/test-contracts/ExtraAbiCaller.zasm b/system-contracts/contracts/test-contracts/ExtraAbiCaller.zasm index b95b2a08b..30ed1d9f8 100644 --- a/system-contracts/contracts/test-contracts/ExtraAbiCaller.zasm +++ b/system-contracts/contracts/test-contracts/ExtraAbiCaller.zasm @@ -4,14 +4,14 @@ __entry: .func_begin0: sub.s! 0, r2, r0 - jump.eq @.RUNTIME_CODE + jump.eq @RUNTIME_CODE ; deployment code add 32, r0, r1 - st.1 r0, r1 - st.1 r1, r0 - add @CPI0_1[0], r0, r1 - ret.ok.to_label r1, @DEFAULT_FAR_RETURN -.RUNTIME_CODE: + stm.h r0, r1 + stm.h r1, r0 + add code[@CPI0_1], r0, r1 + retl r1, @DEFAULT_FAR_RETURN +RUNTIME_CODE: ; ABI: ; 0-32 address(in the lowest 20 bytes) ; 32-64 msg.value @@ -19,29 +19,31 @@ __entry: ; 384+ calldata ; ; load address into r2 - ld.inc r1, r2, r1 + ldpi r1, r2, r1 ; set msg.value - ld.inc r1, r3, r1 - context.set_context_u128 r3 + ldpi r1, r3, r1 + stvl r3 ; load extra abi data into r3-r12 - ld.inc r1, r3, r1 - ld.inc r1, r4, r1 - ld.inc r1, r5, r1 - ld.inc r1, r6, r1 - ld.inc r1, r7, r1 - ld.inc r1, r8, r1 - ld.inc r1, r9, r1 - ld.inc r1, r10, r1 - ld.inc r1, r11, r1 - ld.inc r1, r12, r1 - ptr.pack.s @CPI0_0[0], r1, r1 - far_call r1, r2, @.CALL_REVERT - ptr.pack.s @CPI0_2[0], r1, r1 - ret.ok r1 + ldpi r1, r3, r1 + ldpi r1, r4, r1 + ldpi r1, r5, r1 + ldpi r1, r6, r1 + ldpi r1, r7, r1 + ldpi r1, r8, r1 + ldpi r1, r9, r1 + ldpi r1, r10, r1 + ldpi r1, r11, r1 + ldpi r1, r12, r1 + pack.s code[@CPI0_0], r1, r1 + callf r1, r2, @.CALL_REVERT + pack.s code[@CPI0_2], r1, r1 + ret r1 .CALL_REVERT: - ptr.pack.s @CPI0_2[0], r1, r1 - ret.revert r1 + pack.s code[@CPI0_2], r1, r1 + rev r1 .func_end0: +DEFAULT_FAR_RETURN: + retl @DEFAULT_FAR_RETURN .note.GNU-stack .rodata ; far call abi: @@ -57,4 +59,4 @@ CPI0_1: .cell 5070602400912917605986812821504 ; 01 00000000 0000000000000000 00000000000000000000000000000000 CPI0_2: - .cell 26959946667150639794667015087019630673637144422540572481103610249216 + .cell 26959946667150639794667015087019630673637144422540572481103610249216 \ No newline at end of file diff --git a/system-contracts/foundry.toml b/system-contracts/foundry.toml index ee3885489..748734ad6 100644 --- a/system-contracts/foundry.toml +++ b/system-contracts/foundry.toml @@ -10,4 +10,4 @@ remappings = [ ] [profile.default.zksync] -zksolc = "1.5.0" +zksolc = "1.5.4" diff --git a/system-contracts/hardhat.config.ts b/system-contracts/hardhat.config.ts index 7ad59a41f..5a6ab2986 100644 --- a/system-contracts/hardhat.config.ts +++ b/system-contracts/hardhat.config.ts @@ -6,8 +6,8 @@ import "@nomiclabs/hardhat-ethers"; import "hardhat-typechain"; // This version of system contracts requires a pre release of the compiler -const COMPILER_VERSION = "1.5.0"; -const PRE_RELEASE_VERSION = "prerelease-a167aa3-code4rena"; +const COMPILER_VERSION = "v1.5.6"; +const PRE_RELEASE_VERSION = "1.5.6"; function getZksolcUrl(): string { // @ts-ignore const platform = { darwin: "macosx", linux: "linux", win32: "windows" }[process.platform]; @@ -16,7 +16,7 @@ function getZksolcUrl(): string { const arch = process.arch === "x64" ? "amd64" : process.arch; const ext = process.platform === "win32" ? ".exe" : ""; - return `https://github.com/matter-labs/era-compiler-solidity/releases/download/${PRE_RELEASE_VERSION}/zksolc-${platform}-${arch}${toolchain}-v${COMPILER_VERSION}${ext}`; + return `https://github.com/matter-labs/era-compiler-solidity/releases/download/${PRE_RELEASE_VERSION}/zksolc-${platform}-${arch}${toolchain}-${COMPILER_VERSION}${ext}`; } console.log(`Using zksolc from ${getZksolcUrl()}`); @@ -26,7 +26,8 @@ export default { compilerSource: "binary", settings: { compilerPath: getZksolcUrl(), - isSystem: true, + enableEraVMExtensions: true, + suppressedErrors: ["sendtransfer"], }, }, zkSyncDeploy: { diff --git a/system-contracts/package.json b/system-contracts/package.json index ef53db110..cf6d474ca 100644 --- a/system-contracts/package.json +++ b/system-contracts/package.json @@ -5,7 +5,7 @@ "license": "MIT", "dependencies": { "@matterlabs/hardhat-zksync-deploy": "^0.7.0", - "@matterlabs/hardhat-zksync-solc": "^1.1.4", + "@matterlabs/hardhat-zksync-solc": "^1.2.5", "@matterlabs/hardhat-zksync-verify": "^1.4.3", "commander": "^9.4.1", "eslint": "^8.51.0", diff --git a/system-contracts/scripts/calculate-hashes.ts b/system-contracts/scripts/calculate-hashes.ts index a8fc8036f..e63c3abf8 100644 --- a/system-contracts/scripts/calculate-hashes.ts +++ b/system-contracts/scripts/calculate-hashes.ts @@ -65,7 +65,7 @@ const getSolidityContractsDetails = (dir: string): ContractDetails[] => { const YUL_ARTIFACTS_DIR = "artifacts"; const getYulContractDetails = (dir: string, contractName: string): ContractDetails => { - const bytecodePath = join(dir, YUL_ARTIFACTS_DIR, contractName + ".yul.zbin"); + const bytecodePath = join(dir, YUL_ARTIFACTS_DIR, contractName + ".yul", contractName + ".yul.zbin"); const sourceCodePath = join(dir, contractName + ".yul"); return { contractName, @@ -102,7 +102,7 @@ const readBytecode = (details: ContractDetails): string => { const jsonFile = fs.readFileSync(absolutePath, "utf8"); return ethers.utils.hexlify(JSON.parse(jsonFile).bytecode); } else { - return ethers.utils.hexlify(fs.readFileSync(absolutePath)); + return ethers.utils.hexlify(fs.readFileSync(absolutePath).toString(), { allowMissingPrefix: true }); } } catch (err) { const msg = err instanceof Error ? err.message : "Unknown error"; diff --git a/system-contracts/scripts/compile-yul.ts b/system-contracts/scripts/compile-yul.ts index 67b468987..e22f26b97 100644 --- a/system-contracts/scripts/compile-yul.ts +++ b/system-contracts/scripts/compile-yul.ts @@ -1,18 +1,11 @@ // hardhat import should be the first import in the file import type { CompilerPaths } from "./utils"; -import { - spawn, - compilerLocation, - prepareCompilerPaths, - getSolcLocation, - needsRecompilation, - setCompilationTime, -} from "./utils"; +import { spawn, compilerLocation, prepareCompilerPaths, needsRecompilation, setCompilationTime } from "./utils"; 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.6"; const IS_COMPILER_PRE_RELEASE = true; const CONTRACTS_DIR = "contracts-preprocessed"; const BOOTLOADER_DIR = "bootloader"; @@ -20,11 +13,9 @@ const TIMESTAMP_FILE_YUL = "last_compilation_yul.timestamp"; const TIMESTAMP_FILE_BOOTLOADER = "last_compilation_bootloader.timestamp"; export async function compileYul(paths: CompilerPaths, file: string) { - const solcCompilerPath = await getSolcLocation(); - const zksolcLocation = await compilerLocation(COMPILER_VERSION, IS_COMPILER_PRE_RELEASE); await spawn( - `${zksolcLocation} ${paths.absolutePathSources}/${file} --solc ${solcCompilerPath} --optimization 3 --system-mode --yul --bin --overwrite -o ${paths.absolutePathArtifacts}` + `${zksolcLocation} ${paths.absolutePathSources}/${file} --optimization 3 --enable-eravm-extensions --yul --bin --overwrite -o ${paths.absolutePathArtifacts}` ); } diff --git a/system-contracts/scripts/compile-zasm.ts b/system-contracts/scripts/compile-zasm.ts index 2e6e828a9..8ae15bf16 100644 --- a/system-contracts/scripts/compile-zasm.ts +++ b/system-contracts/scripts/compile-zasm.ts @@ -3,13 +3,13 @@ import type { CompilerPaths } from "./utils"; import { spawn, compilerLocation, prepareCompilerPaths } from "./utils"; import * as fs from "fs"; -const COMPILER_VERSION = "1.3.18"; +const COMPILER_VERSION = "1.5.6"; const IS_COMPILER_PRE_RELEASE = true; export async function compileZasm(paths: CompilerPaths, file: string) { const zksolcLocation = await compilerLocation(COMPILER_VERSION, IS_COMPILER_PRE_RELEASE); await spawn( - `${zksolcLocation} ${paths.absolutePathSources}/${file} --zkasm --bin --overwrite -o ${paths.absolutePathArtifacts}` + `${zksolcLocation} ${paths.absolutePathSources}/${file} --eravm-assembly --bin --overwrite -o ${paths.absolutePathArtifacts}` ); } diff --git a/system-contracts/scripts/deploy-preimages.ts b/system-contracts/scripts/deploy-preimages.ts index 0029f56a0..69ebdd49c 100644 --- a/system-contracts/scripts/deploy-preimages.ts +++ b/system-contracts/scripts/deploy-preimages.ts @@ -13,7 +13,14 @@ import { Provider, Wallet } from "zksync-ethers"; import { hashBytecode } from "zksync-ethers/build/utils"; import { Language, SYSTEM_CONTRACTS } from "./constants"; import type { Dependency, DeployedDependency } from "./utils"; -import { checkMarkers, filterPublishedFactoryDeps, getBytecodes, publishFactoryDeps, readYulBytecode } from "./utils"; +import { + checkMarkers, + filterPublishedFactoryDeps, + getBytecodes, + publishFactoryDeps, + readBytecodeUtf8, + readYulBytecode, +} from "./utils"; const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, "etc/test_config/constant"); const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: "utf-8" })); @@ -189,7 +196,7 @@ class ZkSyncDeployer { } async processBootloader() { - const bootloaderCode = ethers.utils.hexlify(fs.readFileSync("./bootloader/build/artifacts/proved_batch.yul.zbin")); + const bootloaderCode = readBytecodeUtf8("./bootloader/build/artifacts/proved_batch.yul.zbin"); await this.publishBootloader(bootloaderCode); await this.checkShouldUpgradeBootloader(bootloaderCode); diff --git a/system-contracts/scripts/utils.ts b/system-contracts/scripts/utils.ts index 4c1060ee2..cfba8345a 100644 --- a/system-contracts/scripts/utils.ts +++ b/system-contracts/scripts/utils.ts @@ -34,14 +34,18 @@ export interface DeployedDependency { export function readYulBytecode(description: YulContractDescription) { const contractName = description.codeName; - const path = `contracts-preprocessed/${description.path}/artifacts/${contractName}.yul.zbin`; - return ethers.utils.hexlify(fs.readFileSync(path)); + const path = `contracts-preprocessed/${description.path}/artifacts/${contractName}.yul/${contractName}.yul.zbin`; + return readBytecodeUtf8(path); } export function readZasmBytecode(description: ZasmContractDescription) { const contractName = description.codeName; - const path = `contracts-preprocessed/${description.path}/artifacts/${contractName}.zasm.zbin`; - return ethers.utils.hexlify(fs.readFileSync(path)); + const path = `contracts-preprocessed/${description.path}/artifacts/${contractName}.zasm/${contractName}.zasm.zbin`; + return readBytecodeUtf8(path); +} + +export function readBytecodeUtf8(path: string) { + return ethers.utils.hexlify(fs.readFileSync(path).toString(), { allowMissingPrefix: true }); } // The struct used to represent the parameters of a forced deployment -- a deployment during upgrade diff --git a/yarn.lock b/yarn.lock index 66cd67b1a..4df7c8718 100644 --- a/yarn.lock +++ b/yarn.lock @@ -772,6 +772,23 @@ sinon-chai "^3.7.0" undici "^5.14.0" +"@matterlabs/hardhat-zksync-solc@^1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-1.2.5.tgz#fbeeabc3fea0dd232fa3c8cb31bd93c103eba11a" + integrity sha512-iZyznWl1Hoe/Z46hnUe1s2drBZBjJOS/eN+Ql2lIBX9B6NevBl9DYzkKzH5HEIMCLGnX9sWpRAJqUQJWy9UB6w== + dependencies: + "@nomiclabs/hardhat-docker" "^2.0.2" + chai "^4.3.4" + chalk "^4.1.2" + debug "^4.3.5" + dockerode "^4.0.2" + fs-extra "^11.2.0" + proper-lockfile "^4.1.2" + semver "^7.6.2" + sinon "^18.0.0" + sinon-chai "^3.7.0" + undici "^6.18.2" + "@matterlabs/hardhat-zksync-verify@0.6.1": version "0.6.1" resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-verify/-/hardhat-zksync-verify-0.6.1.tgz#3fd83f4177ac0b138656ed93d4756ec27f1d329d" @@ -1181,7 +1198,7 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.1" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.1" -"@nomiclabs/hardhat-docker@^2.0.0": +"@nomiclabs/hardhat-docker@^2.0.0", "@nomiclabs/hardhat-docker@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-docker/-/hardhat-docker-2.0.2.tgz#ae964be17951275a55859ff7358e9e7c77448846" integrity sha512-XgGEpRT3wlA1VslyB57zyAHV+oll8KnV1TjwnxxC1tpAL04/lbdwpdO5KxInVN8irMSepqFpsiSkqlcnvbE7Ng== @@ -1413,20 +1430,27 @@ dependencies: type-detect "4.0.8" -"@sinonjs/commons@^3.0.0": +"@sinonjs/commons@^3.0.0", "@sinonjs/commons@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@^11.2.2": +"@sinonjs/fake-timers@11.2.2", "@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== dependencies: "@sinonjs/commons" "^3.0.0" +"@sinonjs/fake-timers@^13.0.1": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz#3ffe88abb062067a580fdfba706ad00435a0f2a6" + integrity sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA== + dependencies: + "@sinonjs/commons" "^3.0.1" + "@sinonjs/samsam@^8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.0.tgz#0d488c91efb3fa1442e26abea81759dfc8b5ac60" @@ -1441,6 +1465,11 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== +"@sinonjs/text-encoding@^0.7.3": + 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== + "@solidity-parser/parser@^0.14.0": version "0.14.5" resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" @@ -2549,6 +2578,19 @@ chai@^4.3.10, chai@^4.3.6, chai@^4.3.7: pathval "^1.1.1" type-detect "^4.0.8" +chai@^4.3.4: + version "4.5.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8" + integrity sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" + pathval "^1.1.1" + type-detect "^4.1.0" + chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -2961,6 +3003,13 @@ debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.5: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" @@ -3041,7 +3090,7 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diff@^5.1.0: +diff@^5.1.0, diff@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== @@ -4004,7 +4053,7 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^11.1.1: +fs-extra@^11.1.1, fs-extra@^11.2.0: version "11.2.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== @@ -5774,7 +5823,7 @@ 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.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -5815,6 +5864,17 @@ nise@^5.1.5: just-extend "^6.2.0" path-to-regexp "^6.2.1" +nise@^6.0.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/nise/-/nise-6.1.1.tgz#78ea93cc49be122e44cb7c8fdf597b0e8778b64a" + integrity sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g== + dependencies: + "@sinonjs/commons" "^3.0.1" + "@sinonjs/fake-timers" "^13.0.1" + "@sinonjs/text-encoding" "^0.7.3" + just-extend "^6.2.0" + path-to-regexp "^8.1.0" + 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" @@ -6102,6 +6162,11 @@ path-to-regexp@^6.2.1: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz#324377a83e5049cbecadc5554d6a63a9a4866b36" integrity sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw== +path-to-regexp@^8.1.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.2.0.tgz#73990cc29e57a3ff2a0d914095156df5db79e8b4" + integrity sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -6696,6 +6761,11 @@ semver@^7.3.7: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.1.tgz#60bfe090bf907a25aa8119a72b9f90ef7ca281b2" integrity sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA== +semver@^7.6.2: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" @@ -6809,6 +6879,18 @@ sinon@^17.0.1: nise "^5.1.5" supports-color "^7.2.0" +sinon@^18.0.0: + version "18.0.1" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-18.0.1.tgz#464334cdfea2cddc5eda9a4ea7e2e3f0c7a91c5e" + integrity sha512-a2N2TDY1uGviajJ6r4D1CyRAkzE9NNVlYOV1wX5xQDuAk0ONgzgRl0EjCQuRCPxOwp13ghsMwt9Gdldujs39qw== + dependencies: + "@sinonjs/commons" "^3.0.1" + "@sinonjs/fake-timers" "11.2.2" + "@sinonjs/samsam" "^8.0.0" + diff "^5.2.0" + nise "^6.0.0" + supports-color "^7" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -7159,7 +7241,7 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0, supports-color@^7.2.0: +supports-color@^7, 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== @@ -7485,6 +7567,11 @@ type-detect@4.0.8, type-detect@^4.0.0, type-detect@^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.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" @@ -7635,6 +7722,11 @@ 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" @@ -7931,10 +8023,3 @@ zksync-ethers@^5.9.0: integrity sha512-Y2Mx6ovvxO6UdC2dePLguVzvNToOY8iLWeq5ne+jgGSJxAi/f4He/NF6FNsf6x1aWX0o8dy4Df8RcOQXAkj5qw== dependencies: ethers "~5.7.0" - -zksync-web3@^0.15.4: - version "0.15.5" - resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.15.5.tgz#aabe379464963ab573e15948660a709f409b5316" - integrity sha512-97gB7OKJL4spegl8fGO54g6cvTd/75G6yFWZWEa2J09zhjTrfqabbwE/GwiUJkFQ5BbzoH4JaTlVz1hoYZI+DQ== - dependencies: - ethers "~5.7.0" From 59f45ba3282cbea60c3e978b8d17c7661da5a16d Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 18 Oct 2024 10:16:34 +0200 Subject: [PATCH 073/183] chore(EVM): Update from dev (#947) Signed-off-by: Danil Co-authored-by: kelemeno <34402761+kelemeno@users.noreply.github.com> Co-authored-by: Danil Co-authored-by: Vlad Bochok <41153528+vladbochok@users.noreply.github.com> --- .github/workflows/system-contracts-ci.yaml | 2 +- .gitignore | 2 + .../deploy-scripts/DeployL2Contracts.sol | 54 +- l1-contracts/deploy-scripts/Utils.sol | 2 +- .../dev/SetupLegacyBridge.s.sol | 155 + l1-contracts/scripts/utils.ts | 7 +- .../test/unit_tests/custom_base_token.spec.ts | 3 +- .../unit_tests/l1_shared_bridge_test.spec.ts | 6 +- .../test/unit_tests/l2-upgrade.test.spec.ts | 2 +- .../test/unit_tests/legacy_era_test.spec.ts | 2 +- .../test/unit_tests/mailbox_test.spec.ts | 2 +- .../test/unit_tests/proxy_test.spec.ts | 6 +- system-contracts/SystemContractsHashes.json | 104 +- .../bootloader/test_infra/Cargo.lock | 3832 ++++++++++------- .../bootloader/test_infra/Cargo.toml | 12 +- .../bootloader/test_infra/rust-toolchain | 2 +- .../bootloader/test_infra/src/hook.rs | 6 +- .../bootloader/test_infra/src/main.rs | 53 +- .../test_infra/src/test_count_tracer.rs | 8 +- .../bootloader/test_infra/src/tracer.rs | 13 +- system-contracts/contracts/EvmGasManager.sol | 2 +- .../test-contracts/ExtraAbiCaller.zasm | 54 +- system-contracts/foundry.toml | 2 +- system-contracts/hardhat.config.ts | 9 +- system-contracts/package.json | 2 +- system-contracts/scripts/calculate-hashes.ts | 4 +- system-contracts/scripts/compile-yul.ts | 15 +- system-contracts/scripts/compile-zasm.ts | 4 +- system-contracts/scripts/deploy-preimages.ts | 11 +- system-contracts/scripts/utils.ts | 12 +- yarn.lock | 113 +- 31 files changed, 2764 insertions(+), 1737 deletions(-) create mode 100644 l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol diff --git a/.github/workflows/system-contracts-ci.yaml b/.github/workflows/system-contracts-ci.yaml index f842214d6..98d005a35 100644 --- a/.github/workflows/system-contracts-ci.yaml +++ b/.github/workflows/system-contracts-ci.yaml @@ -64,7 +64,7 @@ jobs: - name: Install rust uses: actions-rust-lang/setup-rust-toolchain@v1 with: - toolchain: nightly-2023-04-17 + toolchain: nightly-2024-08-01 - name: Restore artifacts cache uses: actions/cache/restore@v3 diff --git a/.gitignore b/.gitignore index 21c173828..21516dc8e 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ l1-contracts/script-config/* l1-contracts/script-out/* !l1-contracts/script-out/.gitkeep *.timestamp +l1-contracts/test/foundry/l1/integration/deploy-scripts/script-out/* +l1-contracts/zkout/* diff --git a/l1-contracts/deploy-scripts/DeployL2Contracts.sol b/l1-contracts/deploy-scripts/DeployL2Contracts.sol index 1a02fd391..fb3f35024 100644 --- a/l1-contracts/deploy-scripts/DeployL2Contracts.sol +++ b/l1-contracts/deploy-scripts/DeployL2Contracts.sol @@ -46,12 +46,20 @@ contract DeployL2Script is Script { } function run() public { + deploy(false); + } + + function runWithLegacyBridge() public { + deploy(true); + } + + function deploy(bool legacyBridge) public { initializeConfig(); - loadContracts(); + loadContracts(legacyBridge); deployFactoryDeps(); deploySharedBridge(); - deploySharedBridgeProxy(); + deploySharedBridgeProxy(legacyBridge); initializeChain(); deployForceDeployer(); deployConsensusRegistry(); @@ -60,13 +68,21 @@ contract DeployL2Script is Script { saveOutput(); } + function runDeployLegacySharedBridge() public { + deploySharedBridge(true); + } + function runDeploySharedBridge() public { + deploySharedBridge(false); + } + + function deploySharedBridge(bool legacyBridge) internal { initializeConfig(); - loadContracts(); + loadContracts(legacyBridge); deployFactoryDeps(); deploySharedBridge(); - deploySharedBridgeProxy(); + deploySharedBridgeProxy(legacyBridge); initializeChain(); saveOutput(); @@ -74,7 +90,7 @@ contract DeployL2Script is Script { function runDefaultUpgrader() public { initializeConfig(); - loadContracts(); + loadContracts(false); deployForceDeployer(); @@ -83,7 +99,7 @@ contract DeployL2Script is Script { function runDeployConsensusRegistry() public { initializeConfig(); - loadContracts(); + loadContracts(false); deployConsensusRegistry(); deployConsensusRegistryProxy(); @@ -91,7 +107,7 @@ contract DeployL2Script is Script { saveOutput(); } - function loadContracts() internal { + function loadContracts(bool legacyBridge) internal { //HACK: Meanwhile we are not integrated foundry zksync we use contracts that has been built using hardhat contracts.l2StandardErc20FactoryBytecode = Utils.readHardhatBytecode( "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.json" @@ -103,9 +119,16 @@ contract DeployL2Script is Script { "/../l2-contracts/artifacts-zk/contracts/bridge/L2StandardERC20.sol/L2StandardERC20.json" ); - contracts.l2SharedBridgeBytecode = Utils.readFoundryBytecode( - "/../l2-contracts/zkout/L2SharedBridge.sol/L2SharedBridge.json" - ); + if (legacyBridge) { + contracts.l2SharedBridgeBytecode = Utils.readHardhatBytecode( + "/../l2-contracts/artifacts-zk/contracts/dev-contracts/DevL2SharedBridge.sol/DevL2SharedBridge.json" + ); + } else { + contracts.l2SharedBridgeBytecode = Utils.readHardhatBytecode( + "/../l2-contracts/zkout/L2SharedBridge.sol/L2SharedBridge.json" + ); + } + contracts.l2SharedBridgeProxyBytecode = Utils.readHardhatBytecode( "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json" ); @@ -186,13 +209,20 @@ contract DeployL2Script is Script { }); } - function deploySharedBridgeProxy() internal { + function deploySharedBridgeProxy(bool legacyBridge) internal { address l2GovernorAddress = AddressAliasHelper.applyL1ToL2Alias(config.governance); bytes32 l2StandardErc20BytecodeHash = L2ContractHelper.hashL2Bytecode(contracts.beaconProxy); + string memory functionSignature; + + if (legacyBridge) { + functionSignature = "initializeDevBridge(address,address,bytes32,address)"; + } else { + functionSignature = "initialize(address,address,bytes32,address)"; + } // solhint-disable-next-line func-named-parameters bytes memory proxyInitializationParams = abi.encodeWithSignature( - "initialize(address,address,bytes32,address)", + functionSignature, config.l1SharedBridgeProxy, config.erc20BridgeProxy, l2StandardErc20BytecodeHash, diff --git a/l1-contracts/deploy-scripts/Utils.sol b/l1-contracts/deploy-scripts/Utils.sol index 440eadcac..ad8c96094 100644 --- a/l1-contracts/deploy-scripts/Utils.sol +++ b/l1-contracts/deploy-scripts/Utils.sol @@ -109,7 +109,7 @@ library Utils { * @dev Returns the bytecode hash of the batch bootloader. */ function getBatchBootloaderBytecodeHash() internal view returns (bytes memory) { - return vm.readFileBinary("../system-contracts/bootloader/build/artifacts/proved_batch.yul.zbin"); + return vm.readFile("../system-contracts/bootloader/build/artifacts/proved_batch.yul/proved_batch.yul.zbin"); } /** diff --git a/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol new file mode 100644 index 000000000..301bfd2c8 --- /dev/null +++ b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Script} from "forge-std/Script.sol"; +import {stdToml} from "forge-std/StdToml.sol"; +import {Utils} from "./../Utils.sol"; +import {L1SharedBridge} from "contracts/bridge/L1SharedBridge.sol"; +import {DummyL1ERC20Bridge} from "contracts/dev-contracts/DummyL1ERC20Bridge.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; + +/// This scripts is only for developer +contract SetupLegacyBridge is Script { + using stdToml for string; + + Config internal config; + Addresses internal addresses; + + struct Config { + uint256 chainId; + address l2SharedBridgeAddress; + bytes32 create2FactorySalt; + } + + struct Addresses { + address create2FactoryAddr; + address bridgehub; + address diamondProxy; + address sharedBridgeProxy; + address transparentProxyAdmin; + address erc20BridgeProxy; + address tokenWethAddress; + address erc20BridgeProxyImpl; + address sharedBridgeProxyImpl; + } + + function run() public { + initializeConfig(); + deploySharedBridgeImplementation(); + upgradeImplementation(addresses.sharedBridgeProxy, addresses.sharedBridgeProxyImpl); + deployDummyErc20Bridge(); + upgradeImplementation(addresses.erc20BridgeProxy, addresses.erc20BridgeProxyImpl); + setParamsForDummyBridge(); + } + + function initializeConfig() internal { + string memory root = vm.projectRoot(); + string memory path = string.concat(root, "/script-config/setup-legacy-bridge.toml"); + string memory toml = vm.readFile(path); + + addresses.bridgehub = toml.readAddress("$.bridgehub"); + addresses.diamondProxy = toml.readAddress("$.diamond_proxy"); + addresses.sharedBridgeProxy = toml.readAddress("$.shared_bridge_proxy"); + addresses.transparentProxyAdmin = toml.readAddress("$.transparent_proxy_admin"); + addresses.erc20BridgeProxy = toml.readAddress("$.erc20bridge_proxy"); + addresses.tokenWethAddress = toml.readAddress("$.token_weth_address"); + addresses.create2FactoryAddr = toml.readAddress("$.create2factory_addr"); + config.chainId = toml.readUint("$.chain_id"); + config.l2SharedBridgeAddress = toml.readAddress("$.l2shared_bridge_address"); + config.create2FactorySalt = toml.readBytes32("$.create2factory_salt"); + } + + // We need to deploy new shared bridge for changing chain id and diamond proxy address + function deploySharedBridgeImplementation() internal { + bytes memory bytecode = abi.encodePacked( + type(L1SharedBridge).creationCode, + // solhint-disable-next-line func-named-parameters + abi.encode(addresses.tokenWethAddress, addresses.bridgehub, config.chainId, addresses.diamondProxy) + ); + + address contractAddress = deployViaCreate2(bytecode); + addresses.sharedBridgeProxyImpl = contractAddress; + } + + function deployDummyErc20Bridge() internal { + bytes memory bytecode = abi.encodePacked( + type(DummyL1ERC20Bridge).creationCode, + // solhint-disable-next-line func-named-parameters + abi.encode(addresses.sharedBridgeProxy) + ); + address contractAddress = deployViaCreate2(bytecode); + addresses.erc20BridgeProxyImpl = contractAddress; + } + + function upgradeImplementation(address proxy, address implementation) internal { + bytes memory proxyAdminUpgradeData = abi.encodeCall( + ProxyAdmin.upgrade, + (ITransparentUpgradeableProxy(proxy), implementation) + ); + ProxyAdmin _proxyAdmin = ProxyAdmin(addresses.transparentProxyAdmin); + address governance = _proxyAdmin.owner(); + + Utils.executeUpgrade({ + _governor: address(governance), + _salt: bytes32(0), + _target: address(addresses.transparentProxyAdmin), + _data: proxyAdminUpgradeData, + _value: 0, + _delay: 0 + }); + } + + function setParamsForDummyBridge() internal { + (address l2TokenBeacon, bytes32 l2TokenBeaconHash) = calculateTokenBeaconAddress(); + DummyL1ERC20Bridge bridge = DummyL1ERC20Bridge(addresses.erc20BridgeProxy); + bridge.setValues(config.l2SharedBridgeAddress, l2TokenBeacon, l2TokenBeaconHash); + } + + function calculateTokenBeaconAddress() + internal + returns (address tokenBeaconAddress, bytes32 tokenBeaconBytecodeHash) + { + bytes memory l2StandardTokenCode = Utils.readHardhatBytecode( + "/../l2-contracts/artifacts-zk/contracts/bridge/L2StandardERC20.sol/L2StandardERC20.json" + ); + (address l2StandardToken, ) = calculateL2Create2Address( + config.l2SharedBridgeAddress, + l2StandardTokenCode, + bytes32(0), + "" + ); + + bytes memory beaconProxy = Utils.readHardhatBytecode( + "/../l2-contracts/artifacts-zk/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.json" + ); + + (tokenBeaconAddress, tokenBeaconBytecodeHash) = calculateL2Create2Address( + config.l2SharedBridgeAddress, + beaconProxy, + bytes32(0), + abi.encode(l2StandardToken) + ); + } + + function calculateL2Create2Address( + address sender, + bytes memory bytecode, + bytes32 create2salt, + bytes memory constructorargs + ) internal returns (address create2Address, bytes32 bytecodeHash) { + bytecodeHash = L2ContractHelper.hashL2Bytecode(bytecode); + + create2Address = L2ContractHelper.computeCreate2Address( + sender, + create2salt, + bytecodeHash, + keccak256(constructorargs) + ); + } + + function deployViaCreate2(bytes memory _bytecode) internal returns (address) { + return Utils.deployViaCreate2(_bytecode, config.create2FactorySalt, addresses.create2FactoryAddr); + } +} diff --git a/l1-contracts/scripts/utils.ts b/l1-contracts/scripts/utils.ts index 7903f708c..a9cbdacd1 100644 --- a/l1-contracts/scripts/utils.ts +++ b/l1-contracts/scripts/utils.ts @@ -59,7 +59,12 @@ export function web3Provider() { export function readBatchBootloaderBytecode() { const bootloaderPath = path.join(process.env.ZKSYNC_HOME as string, "contracts/system-contracts/bootloader"); - return fs.readFileSync(`${bootloaderPath}/build/artifacts/proved_batch.yul.zbin`); + + return readBytecodeUtf8(`${bootloaderPath}/build/artifacts/proved_batch.yul/proved_batch.yul.zbin`); +} + +export function readBytecodeUtf8(path: string) { + return ethers.utils.hexlify(fs.readFileSync(path).toString(), { allowMissingPrefix: true }); } export function readSystemContractsBytecode(fileName: string) { diff --git a/l1-contracts/test/unit_tests/custom_base_token.spec.ts b/l1-contracts/test/unit_tests/custom_base_token.spec.ts index 464298482..b7dce29b1 100644 --- a/l1-contracts/test/unit_tests/custom_base_token.spec.ts +++ b/l1-contracts/test/unit_tests/custom_base_token.spec.ts @@ -147,7 +147,8 @@ describe("Custom base token chain and bridge tests", () => { const revertReason = await getCallRevertReason( l1SharedBridge.connect(randomSigner).finalizeWithdrawal(chainId, 0, 0, 0, "0x", []) ); - expect(revertReason).contains("MalformedMessage"); + console.log(revertReason); + expect(revertReason).contains("L2WithdrawalMessageWrongLength"); }); it("Should revert on finalizing a withdrawal with wrong function selector", async () => { diff --git a/l1-contracts/test/unit_tests/l1_shared_bridge_test.spec.ts b/l1-contracts/test/unit_tests/l1_shared_bridge_test.spec.ts index 31475e241..fb5cf437d 100644 --- a/l1-contracts/test/unit_tests/l1_shared_bridge_test.spec.ts +++ b/l1-contracts/test/unit_tests/l1_shared_bridge_test.spec.ts @@ -129,7 +129,7 @@ describe("Shared Bridge tests", () => { const revertReason = await getCallRevertReason( l1SharedBridge.connect(randomSigner).finalizeWithdrawal(chainId, 0, 0, 0, "0x", [ethers.constants.HashZero]) ); - expect(revertReason).contains("MalformedMessage"); + expect(revertReason).contains("L2WithdrawalMessageWrongLength"); }); it("Should revert on finalizing a withdrawal with wrong message length", async () => { @@ -145,7 +145,7 @@ describe("Shared Bridge tests", () => { [ethers.constants.HashZero] ) ); - expect(revertReason).contains("MalformedMessage"); + expect(revertReason).contains("L2WithdrawalMessageWrongLength"); }); it("Should revert on finalizing a withdrawal with wrong function selector", async () => { @@ -183,7 +183,7 @@ describe("Shared Bridge tests", () => { const revertReason = await getCallRevertReason( l1SharedBridge.connect(randomSigner).finalizeWithdrawal(chainId, 0, 0, 0, "0x", [ethers.constants.HashZero]) ); - expect(revertReason).contains("MalformedMessage"); + expect(revertReason).contains("L2WithdrawalMessageWrongLength"); }); it("Should revert on finalizing a withdrawal with wrong function signature", async () => { 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 41fe17544..3a0b18aa8 100644 --- a/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts +++ b/l1-contracts/test/unit_tests/l2-upgrade.test.spec.ts @@ -42,7 +42,7 @@ import { } from "./utils"; import { packSemver, unpackStringSemVer, addToProtocolVersion } from "../../scripts/utils"; -describe.only("L2 upgrade test", function () { +describe("L2 upgrade test", function () { let proxyExecutor: ExecutorFacet; let proxyAdmin: AdminFacet; let proxyGetters: GettersFacet; diff --git a/l1-contracts/test/unit_tests/legacy_era_test.spec.ts b/l1-contracts/test/unit_tests/legacy_era_test.spec.ts index 0f4f26bd9..44469df8c 100644 --- a/l1-contracts/test/unit_tests/legacy_era_test.spec.ts +++ b/l1-contracts/test/unit_tests/legacy_era_test.spec.ts @@ -164,7 +164,7 @@ describe("Legacy Era tests", function () { const revertReason = await getCallRevertReason( l1ERC20Bridge.connect(randomSigner).finalizeWithdrawal(0, 0, 0, "0x", [ethers.constants.HashZero]) ); - expect(revertReason).contains("MalformedMessage"); + expect(revertReason).contains("L2WithdrawalMessageWrongLength"); }); it("Should revert on finalizing a withdrawal with wrong function signature", async () => { diff --git a/l1-contracts/test/unit_tests/mailbox_test.spec.ts b/l1-contracts/test/unit_tests/mailbox_test.spec.ts index 5bb874381..230f4e46e 100644 --- a/l1-contracts/test/unit_tests/mailbox_test.spec.ts +++ b/l1-contracts/test/unit_tests/mailbox_test.spec.ts @@ -105,7 +105,7 @@ describe("Mailbox tests", function () { ) ); - expect(revertReason).contains("MalformedBytecode"); + expect(revertReason).contains("LengthIsNotDivisibleBy32"); }); it("Should not accept bytecode of even length in words", async () => { diff --git a/l1-contracts/test/unit_tests/proxy_test.spec.ts b/l1-contracts/test/unit_tests/proxy_test.spec.ts index 4f6dc204a..30cb909d2 100644 --- a/l1-contracts/test/unit_tests/proxy_test.spec.ts +++ b/l1-contracts/test/unit_tests/proxy_test.spec.ts @@ -135,14 +135,14 @@ describe("Diamond proxy tests", function () { const proxyAsERC20 = TestnetERC20TokenFactory.connect(proxy.address, proxy.signer); const revertReason = await getCallRevertReason(proxyAsERC20.transfer(proxyAsERC20.address, 0)); - expect(revertReason).contains("InvalidSelector"); + expect(revertReason).contains("F"); }); it("check that proxy reject data with no selector", async () => { const dataWithoutSelector = "0x1122"; const revertReason = await getCallRevertReason(proxy.fallback({ data: dataWithoutSelector })); - expect(revertReason).contains("MalformedCalldata"); + expect(revertReason).contains("Ut"); }); it("should freeze the diamond storage", async () => { @@ -179,7 +179,7 @@ describe("Diamond proxy tests", function () { data: executorFacetSelector3 + "0000000000000000000000000000000000000000000000000000000000000000", }) ); - expect(revertReason).contains("FacetIsFrozen"); + expect(revertReason).contains("q1"); }); it("should be able to call an unfreezable facet when diamondStorage is frozen", async () => { diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index a2a5c8ca2..c4a4cb894 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,224 +3,224 @@ "contractName": "AccountCodeStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x0100008316f1f5fba0ee0278c40250b93c59fb5edb75658bfd2d3eb59e46fc2e", - "sourceCodeHash": "0xc92c3beabb281421f2d6dc9e46f9ba83b9d46f55a4c1d6799dbec2f57c92b98a" + "bytecodeHash": "0x01000077b3a2e71f210798dbc12daf83c3db44a302475ecf0ac867dc2649aa68", + "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010007df001042752bef1c06161539a67ddc09461f32c8ed33402739e75b5787", + "bytecodeHash": "0x010006f183c7aecce751c6e94e7aac21d5c1f1cc732e04aa683c9ed1f3ba52a4", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004dd0d550356d61d5735f7eef2fc8658aebe72e236058242d08615f4840", + "bytecodeHash": "0x0100004703396a30dda1dc9508debedcf1c67871e3a03a84ec6829a6bc13dc30", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100014f5d4ca4d3f10878213fdec3f6cecaa7ad5738385a5047084175690013", + "bytecodeHash": "0x0100013fc867576077f4db1a5132bd19a62150ae5ae90e39a39c5e15fee1f87c", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x0100075982594cce9610e02a1043cf1bc0c9163045e646ac5b91534708f1dc2e", - "sourceCodeHash": "0x83e503214f41dc6677a100378f48961d459750017fc03dc5b8227c2ddddeba8b" + "bytecodeHash": "0x0100062b38145654a769280b0c6f989d3ca348f117f5476d6f9d9417926be472", + "sourceCodeHash": "0xa1adab82a0cc20a33f53059520bf256e3a01e704f49c7dab528a26c21f8fcb14" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x01000049d9a335e68cabc6be9103b1ce5bb12bc061eb9174105eaa4a03f6a2b3", + "bytecodeHash": "0x0100003ff6c98eb1f7ed6920cc59c447f2fd5e5d96a94ab7a10354dcb315e3c4", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100058de8a8fda78449f14bece247271bdbba5dc73fc96135c35a17ee4dd090", + "bytecodeHash": "0x010005037272b2cbe84aa944a3c8891dd761a28c9c5bef947894b731d1b814c3", "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { "contractName": "EmptyContract", "bytecodePath": "artifacts-zk/contracts-preprocessed/EmptyContract.sol/EmptyContract.json", "sourceCodePath": "contracts-preprocessed/EmptyContract.sol", - "bytecodeHash": "0x010000078f32964c38fbd138a0369f4723f07ac6f4919c45ef738c18bf874ccd", + "bytecodeHash": "0x01000007947dfd1aab45b52e5998b442bfbd4d565af494fb8082a810c6ed0b50", "sourceCodeHash": "0xcac36c5afafbcff83601f4fbfdff660aa66d8c80ed97b9322d3011c1926b554d" }, { "contractName": "EvmGasManager", "bytecodePath": "artifacts-zk/contracts-preprocessed/EvmGasManager.sol/EvmGasManager.json", "sourceCodePath": "contracts-preprocessed/EvmGasManager.sol", - "bytecodeHash": "0x010000f9b3ed54d84d89d5b3088afc18abe188a0834a8f0753a4e9997fd53224", - "sourceCodeHash": "0x0af32498e20adb67fd8e1af9d47679757379793ec3330b93cf0d8726ca9e0b2a" + "bytecodeHash": "0x0100008148ea7fa07f7ba421637904013bb2421ff55367e8c440eed44df928ae", + "sourceCodeHash": "0x56e3898a4cd8af13abf91fa2296900e0b5f409ee3ca4296a0f08affbe31da244" }, { "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000039220b93fa1579ef897a360af9528e8b2b9f11ee24a836e07f9869879d", + "bytecodeHash": "0x010000330a7a1d11b522a1ad580e4b89b553cbc7f7fb50cdd28b92eccdd2dbff", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cfaa9edbf2c7a4ee998090c0b7f78865f3df19811221a2d814a2eed9bb", + "bytecodeHash": "0x010000bd9bfab7f24e22c2aae3d39f1cdd1c86c152102e378eda2e84ea9964d1", "sourceCodeHash": "0xe07e6543ac09b86042eff5f9067df6db10a4fc039ecb56098a882ee1019c3031" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000299cba1a466f8bf47bfb8e08a2fa82910f0b47dbb0c7ecc21722c6b9627", + "bytecodeHash": "0x010002654ccbe8aebd01bcc004f4106d086c578421a2dafb87704248470e5f53", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x01000103fb54b518a2f4f51a2831d1f15e5bacc93e1ae0c65220a78a7c1f9231", + "bytecodeHash": "0x010000f359f25508b815beaa278ff6743c007c48972aac746fe7af827867cf50", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005ded615ffb3639db7834b9aa49fbd2380fb63e3d5edff7de979d659d7c", + "bytecodeHash": "0x010000594f5e8c6b056fbaad49b2ae4d23c034542ab143831752afd14095864c", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000d9db21a9ac5d34d5e70fb3fd9fd65a51df6f38abb18bfaa29e90600def", - "sourceCodeHash": "0xff1ab1ce15c2e54954077315618822ec8deaeaae79ba4e2899518b8713a7234e" + "bytecodeHash": "0x010000cf90f3f2f80ae737aea3509d2be433139e76e37315b459fcd7946150d1", + "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x0100004714b937ae2caf106ea1ce6c641c0e7d49076b9a9f3124d3a6249c841a", + "bytecodeHash": "0x01000041433d7470dedc89405ccb43b5b7e99ee1b874a5d1b55c02d40c159658", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a5edef8985cb8bf31be024c56392e8a52d42162b12656178ad4450c02d", + "bytecodeHash": "0x010001a544226c8f7069254a18c6bd56efa0bbf3438a582c4abc323b9d789c32", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { "contractName": "EventWriter", - "bytecodePath": "contracts-preprocessed/artifacts/EventWriter.yul.zbin", + "bytecodePath": "contracts-preprocessed/artifacts/EventWriter.yul/EventWriter.yul.zbin", "sourceCodePath": "contracts-preprocessed/EventWriter.yul", - "bytecodeHash": "0x010000159b30cba9e2096353695b63ca5cbf566416a545a6bcb2ff2e4e672f98", + "bytecodeHash": "0x0100001739ee6f13091800b6cac4bd0c2c81dd81b449b6ddf3e663ce098c60ad", "sourceCodeHash": "0xfcf4828bcc109dea5f88c38f428d9ac5e18d5a2767fa4909277802c7e38c1f93" }, { "contractName": "EvmEmulator", - "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul.zbin", + "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cdf5bb7dd8a97faf231a5e1e20f2fe308d6f200c3295c6e3629547cc4a4", - "sourceCodeHash": "0xe1133c2af9e4fc38e845f7fcc23f3cbab37b857013f55b6e7e9bdea28f331c40" + "bytecodeHash": "0x01000bdff42de9af35c542b2391edb91529ebb0f90eb9adf80707c295c8bbd66", + "sourceCodeHash": "0x09dc71f1238d306f0fdbab79197a3c4d299eeaf287c62ecd0da1fb8b85529bcc" }, { "contractName": "CodeOracle", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/CodeOracle.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/CodeOracle.yul/CodeOracle.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/CodeOracle.yul", - "bytecodeHash": "0x01000027d78a39f1406a8eaa2f3e52f93641c58472c1c5d20c0dff0423162de1", + "bytecodeHash": "0x01000023e6a0f618c73d49c0ef7f231343b2d82b35d0f3048c2fad6fd6efaccb", "sourceCodeHash": "0xf4b21b6712a6e2a001a1b8214ac15959e670bd0ff125984486a28e128cb8846d" }, { "contractName": "EcAdd", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcAdd.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcAdd.yul/EcAdd.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/EcAdd.yul", - "bytecodeHash": "0x01000087be6181fcb16bebb0567c58b658eec345822aec1d42d471e84f758b85", + "bytecodeHash": "0x01000085f63553694e753270541123b5e2c2b809f1b883db3ceb830366524a40", "sourceCodeHash": "0xdfec1c5f8c6a93df1c8821f1ac15058a18a640bcbdeb67dc4a017f2153ff1c86" }, { "contractName": "EcMul", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcMul.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcMul.yul/EcMul.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/EcMul.yul", - "bytecodeHash": "0x010000bd553a916fcda3726f7b6b3ccfc17887166982915ced63abc78ba43b66", + "bytecodeHash": "0x010000bbf677d3be4dbbf5dad75e63e87f2b1baf1b457d2507cb58025e26a2bf", "sourceCodeHash": "0x0e3f320c8a9532425b85809bf0a2136e707046a01bf20491ec03c77887516c43" }, { "contractName": "EcPairing", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcPairing.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcPairing.yul/EcPairing.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/EcPairing.yul", - "bytecodeHash": "0x01000f1b5f8dd50a00b502d2663746a49a81a01857b6ee1e1b38c9959142b299", + "bytecodeHash": "0x01000ef38d94382bae33b3ffc36660e56b2df54c49c32963f49153830c36121e", "sourceCodeHash": "0x5d008cedc44e0e52c2567fd2b877916b2ec5e7c80294cf99b66485e50a6f2c12" }, { "contractName": "Ecrecover", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Ecrecover.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Ecrecover.yul/Ecrecover.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/Ecrecover.yul", - "bytecodeHash": "0x010000113d6b03e34605f26aa1fc6fb8953561eb55bb5ea192a5a38f7de3053b", + "bytecodeHash": "0x01000013ffc212bb76a7b9108abff6be1d0746154e36d32e9c69268ef95e556a", "sourceCodeHash": "0x21e03ab7a5f518a21258669c82506b1d4d1141f8fd4f30bb385f9730580ddd3c" }, { "contractName": "Keccak256", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Keccak256.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Keccak256.yul/Keccak256.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/Keccak256.yul", - "bytecodeHash": "0x0100000ff991d5847f1e9c10c5969d0f03b34a25411ad86d5cb3e0d9c3931e0b", + "bytecodeHash": "0x0100000f16ef9261284d26f08a560cd482ff7eb7944fe37ac99113aa4eb75188", "sourceCodeHash": "0xb454e7760732ce1fffc75174c8cf54dca422206cf1e52a29d274b310b574f26d" }, { "contractName": "P256Verify", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/P256Verify.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/P256Verify.yul/P256Verify.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/P256Verify.yul", - "bytecodeHash": "0x010000116595cfcc96291f95d47ede2ce630f25ccbd7428f00dc7f8135fb565a", + "bytecodeHash": "0x0100000ff914846f07b729f21be741f039c13d9c8e7c53e4db3a4c9a9f7e022d", "sourceCodeHash": "0x976b68d0362307313fd1aaea309eaa2d849187f37da451618c70dd3a6ac3cf3c" }, { "contractName": "SHA256", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/SHA256.yul.zbin", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/SHA256.yul/SHA256.yul.zbin", "sourceCodePath": "contracts-preprocessed/precompiles/SHA256.yul", - "bytecodeHash": "0x010000171e4e61b14feacd43cb555bffa5f194d38117132957708dcef83ac15a", + "bytecodeHash": "0x01000017cac2faad1aa8a1fd865fa464fbf092dbd8031dedb52fa6b8632e5b97", "sourceCodeHash": "0xfd4290467e26e992f39db9ca132e78ce99ce042b0254a368f1d7832dc94ddefb" }, { "contractName": "bootloader_test", - "bytecodePath": "bootloader/build/artifacts/bootloader_test.yul.zbin", + "bytecodePath": "bootloader/build/artifacts/bootloader_test.yul/bootloader_test.yul.zbin", "sourceCodePath": "bootloader/build/bootloader_test.yul", - "bytecodeHash": "0x010003cbb1c6b1d380510e6e5cedbe4fd089ba2addabcc774ab882774aad6326", + "bytecodeHash": "0x010003adf0d7654575286de7e85d6ceb7572ca71498e5708313a9e9b3d7918e1", "sourceCodeHash": "0x4cac84261775ca327cf22d8b7595e020d03415e7c13311a8601b81543da1d94d" }, { "contractName": "fee_estimate", - "bytecodePath": "bootloader/build/artifacts/fee_estimate.yul.zbin", + "bytecodePath": "bootloader/build/artifacts/fee_estimate.yul/fee_estimate.yul.zbin", "sourceCodePath": "bootloader/build/fee_estimate.yul", - "bytecodeHash": "0x010009251e961ae39033a0364f8a7a9cd9c0b2f666b8cb0d1941f76e7993bd68", + "bytecodeHash": "0x010008fd08bbea54c1315eb3e83d04f4fe3807d86b6e07a57e1bc22006a1aeda", "sourceCodeHash": "0xaa1836b407eae63dcac7b99cfb91defdbac7baa6f4c049f9118181fff58c37ec" }, { "contractName": "gas_test", - "bytecodePath": "bootloader/build/artifacts/gas_test.yul.zbin", + "bytecodePath": "bootloader/build/artifacts/gas_test.yul/gas_test.yul.zbin", "sourceCodePath": "bootloader/build/gas_test.yul", - "bytecodeHash": "0x010008abf2fc690f5de0eed9dc9e293a86c5e7bc5ddf3032976e51185366e221", + "bytecodeHash": "0x0100086956002b1d347b18a1a4b6d0cbb6136afc0a3cf6cd4371bf087caec0e5", "sourceCodeHash": "0x8c224e2e3c6e7c516ce5fbbbe841ecaaeb239e15e24ac0f2f7b4a8a11e9d9dfa" }, { "contractName": "playground_batch", - "bytecodePath": "bootloader/build/artifacts/playground_batch.yul.zbin", + "bytecodePath": "bootloader/build/artifacts/playground_batch.yul/playground_batch.yul.zbin", "sourceCodePath": "bootloader/build/playground_batch.yul", - "bytecodeHash": "0x0100092b66980e7077c0343560010a03243b607f473a65939b252003501ffc9c", + "bytecodeHash": "0x01000903ffd673549dcae99cd0f01a33fc5679fa600084f084179f9cbe7bf506", "sourceCodeHash": "0x04d534fd13610e0a82531f4d2a466e5b6caf814a50fb3a1b0f7d77918f078d26" }, { "contractName": "proved_batch", - "bytecodePath": "bootloader/build/artifacts/proved_batch.yul.zbin", + "bytecodePath": "bootloader/build/artifacts/proved_batch.yul/proved_batch.yul.zbin", "sourceCodePath": "bootloader/build/proved_batch.yul", - "bytecodeHash": "0x010008bbde6fc402ea3a3d6cb15cb97e70245d3d4e48fb74362d4961b74c16b1", + "bytecodeHash": "0x0100087b232b86e32e87f8acfb75c98a50363eb7ccbe504aae3f7b7e8dd94dbf", "sourceCodeHash": "0x72564482cf4e0e31bd47dbd15729952dd6994508c06f5065c2106920ad8e5a33" } ] diff --git a/system-contracts/bootloader/test_infra/Cargo.lock b/system-contracts/bootloader/test_infra/Cargo.lock index 6fa43fd45..f7a9e30ee 100644 --- a/system-contracts/bootloader/test_infra/Cargo.lock +++ b/system-contracts/bootloader/test_infra/Cargo.lock @@ -2,26 +2,37 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addchain" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" +dependencies = [ + "num-bigint 0.3.3", + "num-integer", + "num-traits", +] + [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -30,12 +41,11 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if 1.0.0", - "getrandom", + "cfg-if", "once_cell", "version_check", "zerocopy", @@ -43,18 +53,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -73,15 +83,45 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "arr_macro" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a105bfda48707cf19220129e78fca01e9639433ffaef4163546ed8fb04120a5" +dependencies = [ + "arr_macro_impl", + "proc-macro-hack", +] + +[[package]] +name = "arr_macro_impl" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "0609c78bd572f4edc74310dfb63a01f5609d53fa8b4dd7c4d98aef3b3e8d72d1" +dependencies = [ + "proc-macro-hack", + "quote 1.0.37", + "syn 1.0.109", +] [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] [[package]] name = "arrayvec" @@ -91,19 +131,41 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", +] [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -116,35 +178,30 @@ dependencies = [ ] [[package]] -name = "atomic-write-file" -version = "0.1.2" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436" -dependencies = [ - "nix", - "rand 0.8.5", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.6.20" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", "axum-core", - "bitflags 1.3.2", "bytes", "futures-util", - "http", - "http-body", - "hyper", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", "itoa", "matchit", "memchr", @@ -153,42 +210,57 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper", - "tower", + "sync_wrapper 1.0.1", + "tower 0.5.1", "tower-layer", "tower-service", ] [[package]] name = "axum-core" -version = "0.3.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" dependencies = [ "async-trait", "bytes", "futures-util", - "http", - "http-body", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", ] +[[package]] +name = "backon" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d67782c3f868daa71d3533538e98a8e13713231969def7536e8039606fc46bf0" +dependencies = [ + "fastrand", + "futures-core", + "pin-project", + "tokio", +] + [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -211,9 +283,15 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -227,36 +305,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" -[[package]] -name = "bellman_ce" -version = "0.3.2" -source = "git+https://github.com/matter-labs/bellman?branch=dev#5520aa2274afe73d281373c92b007a2ecdebfbea" -dependencies = [ - "arrayvec 0.7.4", - "bit-vec", - "blake2s_const", - "blake2s_simd", - "byteorder", - "cfg-if 1.0.0", - "crossbeam 0.7.3", - "futures", - "hex", - "lazy_static", - "num_cpus", - "pairing_ce 0.28.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6", - "serde", - "smallvec", - "tiny-keccak 1.5.0", -] - [[package]] name = "bigdecimal" -version = "0.3.1" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" +checksum = "51d712318a27c7150326677b321a5fa91b55f6d9034ffd67f20319e147d40cee" dependencies = [ - "num-bigint", + "autocfg", + "libm", + "num-bigint 0.4.6", "num-integer", "num-traits", ] @@ -283,12 +340,12 @@ dependencies = [ "lazycell", "peeking_take_while", "prettyplease", - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "regex", "rustc-hash", "shlex", - "syn 2.0.40", + "syn 2.0.79", ] [[package]] @@ -308,9 +365,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -329,31 +386,44 @@ dependencies = [ [[package]] name = "blake2" -version = "0.10.6" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174" dependencies = [ - "digest 0.10.7", + "crypto-mac", + "digest 0.9.0", + "opaque-debug", ] [[package]] name = "blake2" version = "0.10.6" -source = "git+https://github.com/RustCrypto/hashes.git?rev=1f727ce37ff40fa0cce84eb8543a45bdd3ca4a4e#1f727ce37ff40fa0cce84eb8543a45bdd3ca4a4e" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ "digest 0.10.7", ] [[package]] -name = "blake2s_const" -version = "0.6.0" -source = "git+https://github.com/matter-labs/bellman?branch=dev#5520aa2274afe73d281373c92b007a2ecdebfbea" +name = "blake2-rfc_bellman_edition" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc60350286c7c3db13b98e91dbe5c8b6830a6821bc20af5b0c310ce94d74915" dependencies = [ - "arrayref", - "arrayvec 0.5.2", + "arrayvec 0.4.12", + "byteorder", "constant_time_eq", ] +[[package]] +name = "blake2_ce" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90cef65f11dd09a6c58914148161dbf190e5dcc02c87ed2aa47b3b97d3e7ce76" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "blake2s_simd" version = "0.5.11" @@ -371,6 +441,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ + "block-padding", "generic-array", ] @@ -383,11 +454,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + [[package]] name = "blst" -version = "0.3.11" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874" dependencies = [ "cc", "glob", @@ -397,17 +474,17 @@ dependencies = [ [[package]] name = "boojum" -version = "0.2.0" -source = "git+https://github.com/matter-labs/era-boojum.git?branch=main#19988079852ea22576da6b09e39365e6cdc1368f" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ec2f007ff8f90cc459f03e9f30ca1065440170f013c868823646e2e48d0234" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bincode", - "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2 0.10.6", "const_format", "convert_case", - "crossbeam 0.8.2", + "crossbeam", "crypto-bigint 0.5.5", - "cs_derive", "derivative", "ethereum-types", "firestorm", @@ -415,22 +492,22 @@ dependencies = [ "lazy_static", "num-modular", "num_cpus", - "packed_simd", - "pairing_ce 0.28.5 (git+https://github.com/matter-labs/pairing.git)", "rand 0.8.5", "rayon", "serde", "sha2 0.10.8", - "sha3 0.10.6", + "sha3_ce", "smallvec", "unroll", + "zksync_cs_derive", + "zksync_pairing", ] [[package]] name = "borsh" -version = "1.3.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d4d6dafc1a3bb54687538972158f07b2c948bc57d5890df22c0739098b3028" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" dependencies = [ "borsh-derive", "cfg_aliases", @@ -438,23 +515,23 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.3.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4918709cc4dd777ad2b6303ed03cb37f3ca0ccede8c1b0d28ac6db8f4710e0" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ "once_cell", - "proc-macro-crate 2.0.1", - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", "syn_derive", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-slice-cast" @@ -464,9 +541,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytecheck" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -475,20 +552,20 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "bytecount" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" +checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "byteorder" @@ -498,9 +575,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "bzip2-sys" @@ -515,18 +592,18 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -546,12 +623,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "58e804ac3194a48bb129643eb1d62fcc20d18c6b8c181704489353d13120bcd1" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -563,12 +641,6 @@ dependencies = [ "nom", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -577,15 +649,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -593,121 +665,130 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "circuit_encodings" -version = "0.1.40" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.0#39665dffd576cff5007c80dd0e1b5334e230bd3b" +version = "0.140.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf6b7cc842eadb4c250cdc6a8bc1dd97624d9f08bbe54db3e11fb23c3a72be07" dependencies = [ "derivative", "serde", - "zk_evm 1.4.0", - "zkevm_circuits 1.4.0", + "zk_evm 0.140.0", + "zkevm_circuits 0.140.3", ] [[package]] name = "circuit_encodings" -version = "0.1.41" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.1#f7bd71fd4216e2c51ab7b09a95909fe48c75f35b" +version = "0.141.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7898ffbf3cd413576b4b674fe1545a35488c67eb16bd5a4148425e42c2a2b65b" dependencies = [ "derivative", "serde", - "zk_evm 1.4.1", - "zkevm_circuits 1.4.1", + "zk_evm 0.141.0", + "zkevm_circuits 0.141.2", ] [[package]] name = "circuit_encodings" -version = "0.1.42" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.2#3149a162a729581005fbad6dbcef027a3ee1b214" +version = "0.142.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8364ecafcc4b2c896023f8d3af952c52a500aa55f14fd268bb5d9ab07f837369" dependencies = [ "derivative", "serde", - "zk_evm 1.4.1", - "zkevm_circuits 1.4.1", + "zk_evm 0.141.0", + "zkevm_circuits 0.141.2", ] [[package]] name = "circuit_encodings" -version = "0.1.50" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.5.0#394e1c7d1aec06d2f3abd63bdc2ddf0efef5ac49" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67617688c66640c84f9b98ff26d48f7898dca4faeb45241a4f21ec333788e7b" dependencies = [ "derivative", "serde", - "zk_evm 1.5.0", - "zkevm_circuits 1.5.0", + "zk_evm 0.150.5", + "zkevm_circuits 0.150.5", ] [[package]] name = "circuit_sequencer_api" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.3.3#aba8f2a32767b79838aca7d7d00d9d23144df32f" +version = "0.133.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb959b1f8c6bbd8be711994d182e85452a26a5d2213a709290b71c8262af1331" dependencies = [ - "bellman_ce", "derivative", "rayon", "serde", - "zk_evm 1.3.3 (git+https://github.com/matter-labs/era-zk_evm.git?branch=v1.3.3)", + "zk_evm 0.133.0", + "zksync_bellman", ] [[package]] name = "circuit_sequencer_api" -version = "0.1.40" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.0#39665dffd576cff5007c80dd0e1b5334e230bd3b" +version = "0.140.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa5f22311ce609d852d7d9f4943535ea4610aeb785129ae6ff83d5201c4fb387" dependencies = [ - "bellman_ce", - "circuit_encodings 0.1.40", + "circuit_encodings 0.140.3", "derivative", "rayon", "serde", - "zk_evm 1.4.0", + "zk_evm 0.140.0", + "zksync_bellman", ] [[package]] name = "circuit_sequencer_api" -version = "0.1.41" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.1#f7bd71fd4216e2c51ab7b09a95909fe48c75f35b" +version = "0.141.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c47c71d6ba83a8beb0af13af70beffd627f5497caf3d44c6f96363e788b07ea" dependencies = [ - "bellman_ce", - "circuit_encodings 0.1.41", + "circuit_encodings 0.141.2", "derivative", "rayon", "serde", - "zk_evm 1.4.1", + "zk_evm 0.141.0", + "zksync_bellman", ] [[package]] name = "circuit_sequencer_api" -version = "0.1.42" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.4.2#3149a162a729581005fbad6dbcef027a3ee1b214" +version = "0.142.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e264723359e6a1aad98110bdccf1ae3ad596e93e7d31da9e40f6adc07e4add54" dependencies = [ - "bellman_ce", - "circuit_encodings 0.1.42", + "circuit_encodings 0.142.2", "derivative", "rayon", "serde", - "zk_evm 1.4.1", + "zk_evm 0.141.0", + "zksync_bellman", ] [[package]] name = "circuit_sequencer_api" -version = "0.1.50" -source = "git+https://github.com/matter-labs/era-zkevm_test_harness.git?branch=v1.5.0#394e1c7d1aec06d2f3abd63bdc2ddf0efef5ac49" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21017310971d4a051e4a52ad70eed11d1ae69defeca8314f73a3a4bad16705a9" dependencies = [ - "bellman_ce", - "circuit_encodings 0.1.50", + "circuit_encodings 0.150.5", "derivative", "rayon", "serde", + "zksync_bellman", ] [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -730,30 +811,39 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bed69047ed42e52c7e38d6421eeb8ceefb4f2a2b52eed59137f7bad7908f6800" +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const_format" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 1.0.87", + "quote 1.0.37", + "unicode-xid 0.2.6", ] [[package]] @@ -764,9 +854,12 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "convert_case" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "core-foundation" @@ -780,24 +873,24 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc" -version = "3.0.1" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] @@ -809,143 +902,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] -name = "crossbeam" -version = "0.7.3" +name = "crc32fast" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if 0.1.10", - "crossbeam-channel 0.4.4", - "crossbeam-deque 0.7.4", - "crossbeam-epoch 0.8.2", - "crossbeam-queue 0.2.3", - "crossbeam-utils 0.7.2", + "cfg-if", ] [[package]] name = "crossbeam" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-channel 0.5.8", - "crossbeam-deque 0.8.3", - "crossbeam-epoch 0.9.15", - "crossbeam-queue 0.3.8", - "crossbeam-utils 0.8.16", -] - -[[package]] -name = "crossbeam-channel" -version = "0.4.4" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" dependencies = [ - "crossbeam-utils 0.7.2", - "maybe-uninit", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.16", + "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" -dependencies = [ - "crossbeam-epoch 0.8.2", - "crossbeam-utils 0.7.2", - "maybe-uninit", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch 0.9.15", - "crossbeam-utils 0.8.16", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "lazy_static", - "maybe-uninit", - "memoffset 0.5.6", - "scopeguard", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" -dependencies = [ - "autocfg", - "cfg-if 1.0.0", - "crossbeam-utils 0.8.16", - "memoffset 0.9.0", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.2.3" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "maybe-uninit", + "crossbeam-utils", ] [[package]] name = "crossbeam-queue" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.16", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", + "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -988,28 +1007,36 @@ dependencies = [ ] [[package]] -name = "cs_derive" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-boojum.git?branch=main#19988079852ea22576da6b09e39365e6cdc1368f" +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", + "generic-array", + "subtle", +] + +[[package]] +name = "ctor" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" +dependencies = [ + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -1021,9 +1048,44 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", +] + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2 1.0.87", + "quote 1.0.37", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote 1.0.37", + "syn 1.0.109", ] [[package]] @@ -1032,8 +1094,8 @@ version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if 1.0.0", - "hashbrown 0.14.3", + "cfg-if", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -1061,9 +1123,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", @@ -1072,11 +1134,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -1085,44 +1148,37 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "derive_more" -version = "0.99.17" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", + "derive_more-impl", ] [[package]] -name = "derive_more" -version = "1.0.0-beta.6" +name = "derive_more-impl" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7abbfc297053be59290e3152f8cbcd52c8642e0728b69ee187d991d4c1af08d" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ - "derive_more-impl", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", + "unicode-xid 0.2.6", ] [[package]] -name = "derive_more-impl" -version = "1.0.0-beta.6" +name = "diff" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bba3e9872d7c58ce7ef0fcf1844fcc3e23ef2a58377b50df35dd98e42a5726e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", - "unicode-xid", -] +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" @@ -1175,7 +1231,7 @@ version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der 0.7.8", + "der 0.7.9", "digest 0.10.7", "elliptic-curve 0.13.8", "rfc6979 0.4.0", @@ -1195,9 +1251,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", @@ -1210,9 +1266,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" dependencies = [ "serde", ] @@ -1259,20 +1315,32 @@ dependencies = [ [[package]] name = "elsa" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714f766f3556b44e7e4776ad133fcc3445a489517c25c704ace411bb14790194" +checksum = "d98e71ae4df57d214182a2e5cb90230c0192c6ddfcaa05c36453d46a54713e10" dependencies = [ "stable_deref_trait", ] [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" dependencies = [ - "cfg-if 1.0.0", + "once_cell", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -1292,9 +1360,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1315,7 +1383,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "home", "windows-sys 0.48.0", ] @@ -1366,15 +1434,20 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.3" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "ff" @@ -1396,39 +1469,11 @@ dependencies = [ "subtle", ] -[[package]] -name = "ff_ce" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b538e4231443a5b9c507caee3356f016d832cf7393d2d90f03ea3180d4e3fbc" -dependencies = [ - "byteorder", - "ff_derive_ce", - "hex", - "rand 0.4.6", - "serde", -] - -[[package]] -name = "ff_derive_ce" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96fbccd88dbb1fac4ee4a07c2fcc4ca719a74ffbd9d2b9d41d8c8eb073d8b20" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", - "proc-macro2", - "quote", - "serde", - "syn 1.0.109", -] - [[package]] name = "fiat-crypto" -version = "0.2.5" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "findshlibs" @@ -1442,12 +1487,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "finl_unicode" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" - [[package]] name = "firestorm" version = "0.5.1" @@ -1472,6 +1511,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "flume" version = "0.11.0" @@ -1480,7 +1529,7 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.8", + "spin", ] [[package]] @@ -1513,6 +1562,39 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "franklin-crypto" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "971289216ea5c91872e5e0bb6989214b537bbce375d09fabea5c3ccfe031b204" +dependencies = [ + "arr_macro", + "bit-vec", + "blake2 0.9.2", + "blake2-rfc_bellman_edition", + "blake2s_simd", + "boojum", + "byteorder", + "derivative", + "digest 0.9.0", + "hex", + "indexmap 1.9.3", + "itertools 0.10.5", + "lazy_static", + "num-bigint 0.4.6", + "num-derive", + "num-integer", + "num-traits", + "rand 0.4.6", + "serde", + "sha2 0.9.9", + "sha3 0.9.1", + "smallvec", + "splitmut", + "tiny-keccak 1.5.0", + "zksync_bellman", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -1527,9 +1609,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1542,9 +1624,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1552,15 +1634,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1581,44 +1663,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" - -[[package]] -name = "futures-timer" -version = "3.0.2" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1645,20 +1721,22 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -1666,6 +1744,81 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "google-cloud-auth" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1112c453c2e155b3e683204ffff52bcc6d6495d04b68d9e90cd24161270c5058" +dependencies = [ + "async-trait", + "base64 0.21.7", + "google-cloud-metadata", + "google-cloud-token", + "home", + "jsonwebtoken", + "reqwest 0.12.8", + "serde", + "serde_json", + "thiserror", + "time", + "tokio", + "tracing", + "urlencoding", +] + +[[package]] +name = "google-cloud-metadata" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f945a208886a13d07636f38fb978da371d0abc3e34bad338124b9f8c135a8f" +dependencies = [ + "reqwest 0.12.8", + "thiserror", + "tokio", +] + +[[package]] +name = "google-cloud-storage" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc0c5b7469142d91bd77959e69375bede324a5def07c7f29aa0d582586cba305" +dependencies = [ + "anyhow", + "async-stream", + "async-trait", + "base64 0.21.7", + "bytes", + "futures-util", + "google-cloud-auth", + "google-cloud-metadata", + "google-cloud-token", + "hex", + "once_cell", + "percent-encoding", + "pkcs8 0.10.2", + "regex", + "reqwest 0.12.8", + "reqwest-middleware", + "ring", + "serde", + "serde_json", + "sha2 0.10.8", + "thiserror", + "time", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "google-cloud-token" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c12ba8b21d128a2ce8585955246977fbce4415f680ebf9199b6f9d6d725f" +dependencies = [ + "async-trait", +] + [[package]] name = "group" version = "0.12.1" @@ -1690,17 +1843,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http", - "indexmap 2.1.0", + "http 0.2.12", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -1708,64 +1861,70 @@ dependencies = [ ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "h2" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ - "ahash 0.7.7", + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", ] [[package]] -name = "hashbrown" -version = "0.14.3" +name = "handlebars" +version = "3.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "4498fc115fa7d34de968184e473529abb40eeb6be8bc5f7faba3d08c316cb3e3" dependencies = [ - "ahash 0.8.6", - "allocator-api2", + "log", + "pest", + "pest_derive", + "quick-error", + "serde", + "serde_json", ] [[package]] -name = "hashlink" -version = "0.8.4" +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "hashbrown 0.14.3", + "ahash 0.7.8", ] [[package]] -name = "headers" -version = "0.3.9" +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "base64 0.21.5", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", + "ahash 0.8.11", + "allocator-api2", ] [[package]] -name = "headers-core" -version = "0.2.0" +name = "hashbrown" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] -name = "heck" -version = "0.4.1" +name = "hashlink" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "unicode-segmentation", + "hashbrown 0.14.5", ] [[package]] @@ -1776,9 +1935,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1788,9 +1947,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hkdf" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ "hmac", ] @@ -1806,11 +1965,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1826,9 +1985,20 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -1842,15 +2012,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1860,52 +2053,77 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-rustls" -version = "0.24.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", - "http", - "hyper", + "http 1.1.0", + "hyper 1.4.1", + "hyper-util", "rustls", + "rustls-pki-types", "tokio", "tokio-rustls", + "tower-service", ] [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper", + "hyper 1.4.1", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] @@ -1915,17 +2133,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.30", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.4.1", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.4.1", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1945,14 +2198,10 @@ dependencies = [ ] [[package]] -name = "idna" -version = "0.4.0" +name = "ident_case" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" @@ -1997,8 +2246,8 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] @@ -2014,19 +2263,19 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.15.0", ] [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "ipnetwork" @@ -2048,59 +2297,59 @@ dependencies = [ [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itertools" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] [[package]] -name = "jsonrpc-core" -version = "18.0.0" +name = "jsonwebtoken" +version = "9.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" dependencies = [ - "futures", - "futures-executor", - "futures-util", - "log", + "base64 0.21.7", + "js-sys", + "pem", + "ring", "serde", - "serde_derive", "serde_json", + "simple_asn1", ] [[package]] @@ -2109,7 +2358,7 @@ version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa 0.14.8", "elliptic-curve 0.12.3", "sha2 0.10.8", @@ -2117,11 +2366,11 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa 0.16.9", "elliptic-curve 0.13.8", "once_cell", @@ -2131,20 +2380,20 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] @@ -2155,18 +2404,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ - "cfg-if 1.0.0", - "winapi", + "cfg-if", + "windows-targets 0.52.6", ] [[package]] @@ -2193,9 +2442,9 @@ dependencies = [ [[package]] name = "libsqlite3-sys" -version = "0.27.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" dependencies = [ "cc", "pkg-config", @@ -2204,46 +2453,26 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.12" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "pkg-config", "vcpkg", ] -[[package]] -name = "linkme" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e6b0bb9ca88d3c5ae88240beb9683821f903b824ee8381ef9ab4e8522fbfa9" -dependencies = [ - "linkme-impl", -] - -[[package]] -name = "linkme-impl" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b3f61e557a617ec6ba36c79431e1f3b5e100d67cfbdb61ed6ef384298af016" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", -] - [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -2251,9 +2480,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "logos" @@ -2272,10 +2501,10 @@ checksum = "dc487311295e0002e452025d6b580b77bb17286de87b57138f3b5db711cded68" dependencies = [ "beef", "fnv", - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "regex-syntax 0.6.29", - "syn 2.0.40", + "syn 2.0.79", ] [[package]] @@ -2289,9 +2518,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.9.4" +version = "1.11.1+lz4-1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" dependencies = [ "cc", "libc", @@ -2318,45 +2547,21 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "md-5" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "digest 0.10.7", ] [[package]] name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memoffset" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.9.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miette" @@ -2376,9 +2581,9 @@ version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -2387,14 +2592,24 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "mini-moka" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e0b72e7c9042467008b10279fc732326bd605459ae03bda88825909dd19b56" +checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803" dependencies = [ - "crossbeam-channel 0.5.8", - "crossbeam-utils 0.8.16", + "crossbeam-channel", + "crossbeam-utils", "dashmap", "skeptic", "smallvec", @@ -2410,66 +2625,37 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.10" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "multivm" -version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" -dependencies = [ - "anyhow", - "circuit_sequencer_api 0.1.0", - "circuit_sequencer_api 0.1.40", - "circuit_sequencer_api 0.1.41", - "circuit_sequencer_api 0.1.42", - "circuit_sequencer_api 0.1.50", - "hex", - "itertools 0.10.5", - "once_cell", - "thiserror", - "tracing", - "vise", - "zk_evm 1.3.1", - "zk_evm 1.3.3 (git+https://github.com/matter-labs/era-zk_evm.git?tag=v1.3.3-rc2)", - "zk_evm 1.4.0", - "zk_evm 1.4.1", - "zk_evm 1.5.0", - "zksync_contracts", - "zksync_state", - "zksync_system_constants", - "zksync_types", - "zksync_utils", -] +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -2482,15 +2668,10 @@ dependencies = [ ] [[package]] -name = "nix" -version = "0.27.1" +name = "nodrop" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.4.1", - "cfg-if 1.0.0", - "libc", -] +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] name = "nom" @@ -2514,11 +2695,11 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "num-bigint", + "num-bigint 0.4.6", "num-complex", "num-integer", "num-iter", @@ -2528,13 +2709,23 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" dependencies = [ "autocfg", "num-integer", "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", "serde", ] @@ -2557,29 +2748,45 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", "serde", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-derive" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -2598,12 +2805,11 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", - "num-bigint", + "num-bigint 0.4.6", "num-integer", "num-traits", "serde", @@ -2611,9 +2817,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -2640,11 +2846,11 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ - "num_enum_derive 0.7.2", + "num_enum_derive 0.7.3", ] [[package]] @@ -2654,52 +2860,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 2.0.1", - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "object" -version = "0.32.1" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.61" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.4.1", - "cfg-if 1.0.0", + "bitflags 2.6.0", + "cfg-if", "foreign-types", "libc", "once_cell", @@ -2713,9 +2919,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -2726,9 +2932,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.97" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -2738,43 +2944,58 @@ dependencies = [ [[package]] name = "opentelemetry" -version = "0.20.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" +checksum = "4c365a63eec4f55b7efeceb724f1336f26a9cf3427b70e59e2cd2a5b947fba96" dependencies = [ - "opentelemetry_api", - "opentelemetry_sdk", + "futures-core", + "futures-sink", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", +] + +[[package]] +name = "opentelemetry-appender-tracing" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84de945cb3a6f1e0d6317cbd998bbd0519ab00f4b790db67e0ff4fdcf7cedb6" +dependencies = [ + "opentelemetry", + "tracing", + "tracing-core", + "tracing-subscriber", ] [[package]] name = "opentelemetry-http" -version = "0.9.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7594ec0e11d8e33faf03530a4c49af7064ebba81c1480e01be67d90b356508b" +checksum = "ad31e9de44ee3538fb9d64fe3376c1362f406162434609e79aea2a41a0af78ab" dependencies = [ "async-trait", "bytes", - "http", - "opentelemetry_api", - "reqwest", + "http 1.1.0", + "opentelemetry", + "reqwest 0.12.8", ] [[package]] name = "opentelemetry-otlp" -version = "0.13.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5e5a5c4135864099f3faafbe939eb4d7f9b80ebf68a8448da961b32a7c1275" +checksum = "6b925a602ffb916fb7421276b86756027b37ee708f9dce2dbdcc51739f07e727" dependencies = [ "async-trait", "futures-core", - "http", + "http 1.1.0", + "opentelemetry", "opentelemetry-http", "opentelemetry-proto", - "opentelemetry-semantic-conventions", - "opentelemetry_api", "opentelemetry_sdk", - "prost 0.11.9", - "reqwest", + "prost 0.13.3", + "reqwest 0.12.8", "thiserror", "tokio", "tonic", @@ -2782,58 +3003,37 @@ dependencies = [ [[package]] name = "opentelemetry-proto" -version = "0.3.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e3f814aa9f8c905d0ee4bde026afd3b2577a97c10e1699912e3e44f0c4cbeb" +checksum = "30ee9f20bff9c984511a02f082dc8ede839e4a9bf15cc2487c8d6fea5ad850d9" dependencies = [ - "opentelemetry_api", + "opentelemetry", "opentelemetry_sdk", - "prost 0.11.9", + "prost 0.13.3", "tonic", ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.12.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c9f9340ad135068800e7f1b24e9e09ed9e7143f5bf8518ded3d3ec69789269" -dependencies = [ - "opentelemetry", -] - -[[package]] -name = "opentelemetry_api" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" -dependencies = [ - "futures-channel", - "futures-util", - "indexmap 1.9.3", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror", - "urlencoding", -] +checksum = "1cefe0543875379e47eb5f1e68ff83f45cc41366a92dfd0d073d513bf68e9a05" [[package]] name = "opentelemetry_sdk" -version = "0.20.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8e705a0612d48139799fcbaba0d4a90f06277153e43dd2bdc16c6f0edd8026" +checksum = "692eac490ec80f24a17828d49b40b60f5aeaccdfe6a503f939713afd22bc28df" dependencies = [ "async-trait", - "crossbeam-channel 0.5.8", "futures-channel", "futures-executor", "futures-util", + "glob", "once_cell", - "opentelemetry_api", - "ordered-float 3.9.2", + "opentelemetry", "percent-encoding", "rand 0.8.5", - "regex", "serde_json", "thiserror", "tokio", @@ -2849,24 +3049,15 @@ dependencies = [ "num-traits", ] -[[package]] -name = "ordered-float" -version = "3.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" -dependencies = [ - "num-traits", -] - [[package]] name = "os_info" -version = "3.7.0" +version = "3.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e" +checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" dependencies = [ "log", "serde", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -2887,60 +3078,13 @@ dependencies = [ "sha2 0.10.8", ] -[[package]] -name = "packed_simd" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f9f08af0c877571712e2e3e686ad79efad9657dbf0f7c3c8ba943ff6c38932d" -dependencies = [ - "cfg-if 1.0.0", - "num-traits", -] - -[[package]] -name = "pairing_ce" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db007b21259660d025918e653508f03050bf23fb96a88601f9936329faadc597" -dependencies = [ - "byteorder", - "cfg-if 1.0.0", - "ff_ce", - "rand 0.4.6", - "serde", -] - -[[package]] -name = "pairing_ce" -version = "0.28.5" -source = "git+https://github.com/matter-labs/pairing.git?rev=d24f2c5871089c4cd4f54c0ca266bb9fef6115eb#d24f2c5871089c4cd4f54c0ca266bb9fef6115eb" -dependencies = [ - "byteorder", - "cfg-if 1.0.0", - "ff_ce", - "rand 0.4.6", - "serde", -] - -[[package]] -name = "pairing_ce" -version = "0.28.5" -source = "git+https://github.com/matter-labs/pairing.git#d24f2c5871089c4cd4f54c0ca266bb9fef6115eb" -dependencies = [ - "byteorder", - "cfg-if 1.0.0", - "ff_ce", - "rand 0.4.6", - "serde", -] - [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bitvec", "byte-slice-cast", "impl-trait-for-tuples", @@ -2950,21 +3094,27 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.1", - "proc-macro2", - "quote", + "proc-macro-crate 3.2.0", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -2972,22 +3122,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "peeking_take_while" @@ -2995,6 +3145,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +[[package]] +name = "pem" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +dependencies = [ + "base64 0.22.1", + "serde", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -3010,41 +3170,86 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", +] + +[[package]] +name = "pest_meta" +version = "2.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f" +dependencies = [ + "once_cell", + "pest", + "sha2 0.10.8", +] + [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.1.0", + "indexmap 2.6.0", ] [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -3058,7 +3263,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "der 0.7.8", + "der 0.7.9", "pkcs8 0.10.2", "spki 0.7.3", ] @@ -3079,21 +3284,15 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.8", + "der 0.7.9", "spki 0.7.3", ] [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "platforms" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "powerfmt" @@ -3103,18 +3302,31 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "pretty_assertions" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] [[package]] name = "prettyplease" -version = "0.2.15" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ - "proc-macro2", - "syn 2.0.40", + "proc-macro2 1.0.87", + "syn 2.0.79", ] [[package]] @@ -3151,12 +3363,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.22.22", ] [[package]] @@ -3166,8 +3377,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", "version_check", ] @@ -3178,25 +3389,40 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "version_check", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus-client" -version = "0.22.2" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ca959da22a332509f2a73ae9e5f23f9dcfc31fd3a54d71f159495bd5909baa" +checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" dependencies = [ "dtoa", "itoa", @@ -3210,77 +3436,76 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "prost" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive 0.11.9", + "prost-derive 0.12.6", ] [[package]] name = "prost" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", - "prost-derive 0.12.3", + "prost-derive 0.13.3", ] [[package]] name = "prost-build" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.4.1", - "itertools 0.11.0", + "heck", + "itertools 0.12.1", "log", "multimap", "once_cell", "petgraph", "prettyplease", - "prost 0.12.3", + "prost 0.12.6", "prost-types", "regex", - "syn 2.0.40", + "syn 2.0.79", "tempfile", - "which", ] [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", + "itertools 0.12.1", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools 0.11.0", - "proc-macro2", - "quote", - "syn 2.0.40", + "itertools 0.13.0", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -3289,11 +3514,11 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "057237efdb71cf4b3f9396302a3d6599a92fa94063ba537b66130980ea9909f3" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "logos", "miette", "once_cell", - "prost 0.12.3", + "prost 0.12.6", "prost-types", "serde", "serde-value", @@ -3301,11 +3526,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ - "prost 0.12.3", + "prost 0.12.6", ] [[package]] @@ -3316,7 +3541,7 @@ checksum = "00bb76c5f6221de491fe2c8f39b106330bbd9762c6511119c07940e10eb9ff11" dependencies = [ "bytes", "miette", - "prost 0.12.3", + "prost 0.12.6", "prost-reflect", "prost-types", "protox-parse", @@ -3350,22 +3575,28 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "pulldown-cmark" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "memchr", "unicase", ] +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-protobuf" version = "0.8.1" @@ -3377,11 +3608,20 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.87", ] [[package]] @@ -3450,9 +3690,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -3460,12 +3700,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-deque 0.8.3", - "crossbeam-utils 0.8.16", + "crossbeam-deque", + "crossbeam-utils", ] [[package]] @@ -3479,23 +3719,23 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -3509,13 +3749,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", ] [[package]] @@ -3526,36 +3766,35 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rend" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" dependencies = [ "bytecheck", ] [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "hyper-tls", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.30", + "hyper-tls 0.5.0", "ipnet", "js-sys", "log", @@ -3564,24 +3803,109 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", - "system-configuration", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", "tokio", "tokio-native-tls", - "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", "winreg", ] +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-rustls", + "hyper-tls 0.6.0", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.2.0", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "system-configuration 0.6.1", + "tokio", + "tokio-native-tls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "windows-registry", +] + +[[package]] +name = "reqwest-middleware" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562ceb5a604d3f7c885a792d42c199fd8af239d0a51b2fa6a78aafa092452b04" +dependencies = [ + "anyhow", + "async-trait", + "http 1.1.0", + "reqwest 0.12.8", + "serde", + "thiserror", + "tower-service", +] + +[[package]] +name = "rescue_poseidon" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82900c877a0ba5362ac5756efbd82c5b795dc509011c1253e2389d8708f1389d" +dependencies = [ + "addchain", + "arrayvec 0.7.6", + "blake2 0.10.6", + "byteorder", + "derivative", + "franklin-crypto", + "lazy_static", + "log", + "num-bigint 0.3.3", + "num-integer", + "num-iter", + "num-traits", + "rand 0.4.6", + "serde", + "sha3 0.9.1", + "smallvec", + "typemap_rev", +] + [[package]] name = "rfc6979" version = "0.3.1" @@ -3605,23 +3929,24 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", - "spin 0.9.8", + "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "rkyv" -version = "0.7.43" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527a97cdfef66f65998b5f3b637c26f5a5ec09cc52a3f9932313ac645f4190f5" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" dependencies = [ "bitvec", "bytecheck", @@ -3637,12 +3962,12 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.43" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5c462a1328c8e67e4d6dbad1eb0355dd43e8ab432c6e227a43657f16ade5033" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "syn 1.0.109", ] @@ -3688,11 +4013,11 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.33.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06676aec5ccb8fc1da723cc8c0f9a46549f21ebb8753d3915c6c41db1e7f1dc4" +checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "borsh", "bytes", "num-traits", @@ -3704,9 +4029,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -3722,20 +4047,20 @@ checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -3744,14 +4069,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" dependencies = [ - "log", - "ring", + "once_cell", + "rustls-pki-types", "rustls-webpki", - "sct", + "subtle", + "zeroize", ] [[package]] @@ -3760,30 +4086,46 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", ] +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + [[package]] name = "rustls-webpki" -version = "0.101.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", + "rustls-pki-types", "untrusted", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -3796,11 +4138,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -3809,16 +4151,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "seahash" version = "4.1.0" @@ -3846,7 +4178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct 0.2.0", - "der 0.7.8", + "der 0.7.9", "generic-array", "pkcs8 0.10.2", "subtle", @@ -3871,13 +4203,22 @@ dependencies = [ "cc", ] +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -3886,9 +4227,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -3896,9 +4237,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] @@ -3911,7 +4252,7 @@ checksum = "6ce4b57f1b521f674df7a1d200be8ff5d74e3712020ee25b553146657b5377d5" dependencies = [ "httpdate", "native-tls", - "reqwest", + "reqwest 0.11.27", "sentry-backtrace", "sentry-contexts", "sentry-core", @@ -4019,9 +4360,9 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -4032,28 +4373,29 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" dependencies = [ - "ordered-float 2.10.1", + "ordered-float", "serde", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -4071,29 +4413,40 @@ dependencies = [ ] [[package]] -name = "serde_yaml" -version = "0.9.29" +name = "serde_with" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" dependencies = [ - "indexmap 2.1.0", - "itoa", - "ryu", + "base64 0.13.1", + "hex", "serde", - "unsafe-libyaml", + "serde_with_macros", ] [[package]] -name = "sha-1" -version = "0.9.8" +name = "serde_with_macros" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "darling", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 1.0.109", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.6.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", ] [[package]] @@ -4102,19 +4455,22 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] [[package]] name = "sha2" -version = "0.10.6" -source = "git+https://github.com/RustCrypto/hashes.git?rev=1731ced4a116d61ba9dc6ee6d0f38fb8102e357a#1731ced4a116d61ba9dc6ee6d0f38fb8102e357a" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "cfg-if 1.0.0", + "block-buffer 0.9.0", + "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest 0.9.0", + "opaque-debug", ] [[package]] @@ -4123,18 +4479,32 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] [[package]] -name = "sha3" +name = "sha2_ce" version = "0.10.6" -source = "git+https://github.com/RustCrypto/hashes.git?rev=7a187e934c1f6c68e4b4e5cf37541b7a0d64d303#7a187e934c1f6c68e4b4e5cf37541b7a0d64d303" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca2daa77078f4ddff27e75c4bf59e4c2697525f56dbb3c842d34a5d1f2b04a2" dependencies = [ + "cfg-if", + "cpufeatures", "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", "keccak", + "opaque-debug", ] [[package]] @@ -4147,6 +4517,16 @@ dependencies = [ "keccak", ] +[[package]] +name = "sha3_ce" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34c9a08202c50378d8a07a5f458193a5f542d2828ac6640263dbc0c2533ea25e" +dependencies = [ + "digest 0.10.7", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -4158,15 +4538,15 @@ dependencies = [ [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -4193,9 +4573,21 @@ dependencies = [ [[package]] name = "simdutf8" -version = "0.1.4" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "simple_asn1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "thiserror", + "time", +] [[package]] name = "skeptic" @@ -4223,54 +4615,23 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" dependencies = [ "serde", ] [[package]] name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "soketto" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" -dependencies = [ - "base64 0.13.1", - "bytes", - "futures", - "httparse", - "log", - "rand 0.8.5", - "sha-1", + "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -4297,25 +4658,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.8", + "der 0.7.9", ] +[[package]] +name = "splitmut" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85070f382340e8b23a75808e83573ddf65f9ad9143df9573ca37c1ed2ee956a" + [[package]] name = "sqlformat" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" dependencies = [ - "itertools 0.12.0", "nom", "unicode_categories", ] [[package]] name = "sqlx" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" +checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e" dependencies = [ "sqlx-core", "sqlx-macros", @@ -4326,19 +4692,17 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" +checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e" dependencies = [ - "ahash 0.8.6", "atoi", "bigdecimal", "byteorder", "bytes", "chrono", "crc", - "crossbeam-queue 0.3.8", - "dotenvy", + "crossbeam-queue", "either", "event-listener", "futures-channel", @@ -4346,9 +4710,10 @@ dependencies = [ "futures-intrusive", "futures-io", "futures-util", + "hashbrown 0.14.5", "hashlink", "hex", - "indexmap 2.1.0", + "indexmap 2.6.0", "ipnetwork", "log", "memchr", @@ -4371,31 +4736,30 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" +checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "sqlx-core", "sqlx-macros-core", - "syn 1.0.109", + "syn 2.0.79", ] [[package]] name = "sqlx-macros-core" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" +checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" dependencies = [ - "atomic-write-file", "dotenvy", "either", - "heck 0.4.1", + "heck", "hex", "once_cell", - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "serde", "serde_json", "sha2 0.10.8", @@ -4403,7 +4767,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 1.0.109", + "syn 2.0.79", "tempfile", "tokio", "url", @@ -4411,14 +4775,14 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" +checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a" dependencies = [ "atoi", - "base64 0.21.5", + "base64 0.22.1", "bigdecimal", - "bitflags 2.4.1", + "bitflags 2.6.0", "byteorder", "bytes", "chrono", @@ -4456,14 +4820,14 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" +checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8" dependencies = [ "atoi", - "base64 0.21.5", + "base64 0.22.1", "bigdecimal", - "bitflags 2.4.1", + "bitflags 2.6.0", "byteorder", "chrono", "crc", @@ -4482,13 +4846,12 @@ dependencies = [ "log", "md-5", "memchr", - "num-bigint", + "num-bigint 0.4.6", "once_cell", "rand 0.8.5", "rust_decimal", "serde", "serde_json", - "sha1", "sha2 0.10.8", "smallvec", "sqlx-core", @@ -4500,9 +4863,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" +checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" dependencies = [ "atoi", "chrono", @@ -4516,10 +4879,10 @@ dependencies = [ "log", "percent-encoding", "serde", + "serde_urlencoded", "sqlx-core", "tracing", "url", - "urlencoding", ] [[package]] @@ -4536,42 +4899,59 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" -version = "0.24.1" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.24.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", + "heck", + "proc-macro2 1.0.87", + "quote 1.0.37", "rustversion", - "syn 1.0.109", + "syn 2.0.79", ] [[package]] name = "subtle" -version = "2.4.1" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] [[package]] name = "syn" @@ -4579,19 +4959,19 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.40" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.87", + "quote 1.0.37", "unicode-ident", ] @@ -4602,9 +4982,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" dependencies = [ "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -4613,6 +4993,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -4621,7 +5010,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys 0.6.0", ] [[package]] @@ -4634,6 +5034,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tagptr" version = "0.2.0" @@ -4648,15 +5058,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.1" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", - "redox_syscall", + "once_cell", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -4665,46 +5075,46 @@ version = "0.1.0" dependencies = [ "colored", "hex", - "multivm", "once_cell", "serde", "serde_json", "tracing", "tracing-subscriber", - "vlog", "zksync_contracts", + "zksync_multivm", "zksync_state", "zksync_types", "zksync_utils", + "zksync_vlog", ] [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", ] @@ -4719,12 +5129,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -4739,10 +5150,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -4766,9 +5178,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -4781,42 +5193,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -4831,19 +5232,20 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ "rustls", + "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -4852,24 +5254,22 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", - "futures-io", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" @@ -4877,45 +5277,47 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.6.0", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.6.0", "toml_datetime", - "winnow", + "winnow 0.6.20", ] [[package]] name = "tonic" -version = "0.9.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ + "async-stream", "async-trait", "axum", - "base64 0.21.5", + "base64 0.22.1", "bytes", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", - "prost 0.11.9", + "prost 0.13.3", + "socket2", "tokio", "tokio-stream", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -4941,17 +5343,31 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -4971,9 +5387,9 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] @@ -4986,17 +5402,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-log" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -5010,18 +5415,20 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.21.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75327c6b667828ddc28f5e3f169036cb793c3f588d83bf0f262a7f062ffed3c8" +checksum = "a9784ed4da7d921bc8df6963f8c80a0e4ce34ba6ba76668acadd3edbd985ff3b" dependencies = [ + "js-sys", "once_cell", "opentelemetry", "opentelemetry_sdk", "smallvec", "tracing", "tracing-core", - "tracing-log 0.1.4", + "tracing-log", "tracing-subscriber", + "web-time", ] [[package]] @@ -5052,15 +5459,15 @@ dependencies = [ "time", "tracing", "tracing-core", - "tracing-log 0.2.0", + "tracing-log", "tracing-serde", ] [[package]] name = "triomphe" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" +checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" [[package]] name = "try-lock" @@ -5068,12 +5475,24 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typemap_rev" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74b08b0c1257381af16a5c3605254d529d3e7e109f3c62befc5d168968192998" + [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + [[package]] name = "uint" version = "0.9.5" @@ -5106,42 +5525,54 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "unicode-xid" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unicode_categories" @@ -5155,7 +5586,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ad948c1cb799b1a70f836077721a92a35ac177d4daddf4c20a633786d4cf618" dependencies = [ - "quote", + "quote 1.0.37", "syn 1.0.109", ] @@ -5173,11 +5604,11 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" dependencies = [ - "base64 0.21.5", + "base64 0.22.1", "log", "native-tls", "once_cell", @@ -5186,12 +5617,12 @@ dependencies = [ [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna", "percent-encoding", "serde", ] @@ -5204,9 +5635,9 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "uuid" -version = "1.6.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "serde", ] @@ -5225,54 +5656,53 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vise" -version = "0.1.0" -source = "git+https://github.com/matter-labs/vise.git?rev=a5bb80c9ce7168663114ee30e794d6dc32159ee4#a5bb80c9ce7168663114ee30e794d6dc32159ee4" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ade36f3548b1524396f4de7b36f4f210c8a01dfab568eb2bff466af64eb6e5" dependencies = [ "compile-fmt", + "ctor", "elsa", - "linkme", "once_cell", "prometheus-client", "vise-macros", ] [[package]] -name = "vise-macros" -version = "0.1.0" -source = "git+https://github.com/matter-labs/vise.git?rev=a5bb80c9ce7168663114ee30e794d6dc32159ee4#a5bb80c9ce7168663114ee30e794d6dc32159ee4" +name = "vise-exporter" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671d3b894d5d0849f0a597f56bf071f42d4f2a1cbcf2f78ca21f870ab7c0cc2b" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "hyper 0.14.30", + "once_cell", + "tokio", + "tracing", + "vise", ] [[package]] -name = "vlog" -version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +name = "vise-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a511871dc5de990a3b2a0e715facfbc5da848c0c0395597a1415029fb7c250a" dependencies = [ - "chrono", - "opentelemetry", - "opentelemetry-otlp", - "opentelemetry-semantic-conventions", - "sentry", - "serde_json", - "tracing", - "tracing-opentelemetry", - "tracing-subscriber", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -5293,38 +5723,45 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -5332,115 +5769,76 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ - "quote", + "quote 1.0.37", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] -name = "web-sys" -version = "0.3.66" +name = "wasm-streams" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" dependencies = [ + "futures-util", "js-sys", "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] -name = "web3" -version = "0.19.0" +name = "web-sys" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5388522c899d1e1c96a4c307e3797e0f697ba7c77dd8e0e625ecba9dd0342937" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ - "arrayvec 0.7.4", - "base64 0.21.5", - "bytes", - "derive_more 0.99.17", - "ethabi", - "ethereum-types", - "futures", - "futures-timer", - "headers", - "hex", - "idna 0.4.0", - "jsonrpc-core", - "log", - "once_cell", - "parking_lot", - "pin-project", - "reqwest", - "rlp", - "secp256k1", - "serde", - "serde_json", - "soketto", - "tiny-keccak 2.0.2", - "tokio", - "tokio-stream", - "tokio-util", - "url", - "web3-async-native-tls", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "web3-async-native-tls" -version = "0.4.0" +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6d8d1636b2627fe63518d5a9b38a569405d9c9bc665c43c9c341de57227ebb" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ - "native-tls", - "thiserror", - "tokio", - "url", + "js-sys", + "wasm-bindgen", ] [[package]] -name = "webpki-roots" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" - -[[package]] -name = "which" -version = "4.4.2" +name = "whoami" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" dependencies = [ - "either", - "home", - "once_cell", - "rustix", + "redox_syscall", + "wasite", ] -[[package]] -name = "whoami" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" - [[package]] name = "winapi" version = "0.3.9" @@ -5459,11 +5857,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -5474,11 +5872,41 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", ] [[package]] @@ -5496,7 +5924,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -5516,17 +5953,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -5537,9 +5975,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -5549,9 +5987,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -5561,9 +5999,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -5573,9 +6017,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -5585,9 +6029,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -5597,9 +6041,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -5609,15 +6053,24 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] [[package]] name = "winnow" -version = "0.5.26" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67b5f0a4e7a27a64c651977932b9dc5667ca7fc31ac44b03ed37a0cf42fdfff" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -5628,7 +6081,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "windows-sys 0.48.0", ] @@ -5642,30 +6095,37 @@ dependencies = [ ] [[package]] -name = "zerocopy" -version = "0.7.30" +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306dca4455518f1f31635ec308b6b3e4eb1b11758cefafc782827d0aa7acb5c7" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.30" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be912bf68235a88fbefd1b73415cb218405958d1655b2ece9035a19920bdf6ba" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -5676,47 +6136,34 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 2.0.79", ] [[package]] name = "zk_evm" -version = "1.3.1" -source = "git+https://github.com/matter-labs/era-zk_evm.git?tag=v1.3.1-rc2#0a7c775932db4839ff6b7fb0db9bdb3583ab54c0" +version = "0.131.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b83ee7887fb29fda57c6b26a0f64c9b211459d718f8a26310f962e69f0b764" dependencies = [ - "blake2 0.10.6 (git+https://github.com/RustCrypto/hashes.git?rev=1f727ce37ff40fa0cce84eb8543a45bdd3ca4a4e)", + "blake2_ce", "k256 0.11.6", "lazy_static", "num", "serde", "serde_json", - "sha2 0.10.6", - "sha3 0.10.6", - "static_assertions", - "zkevm_opcode_defs 1.3.1", -] - -[[package]] -name = "zk_evm" -version = "1.3.3" -source = "git+https://github.com/matter-labs/era-zk_evm.git?tag=v1.3.3-rc2#fbee20f5bac7d6ca3e22ae69b2077c510a07de4e" -dependencies = [ - "anyhow", - "lazy_static", - "num", - "serde", - "serde_json", + "sha2_ce", + "sha3_ce", "static_assertions", - "zk_evm_abstractions 0.1.0", - "zkevm_opcode_defs 1.3.2", + "zkevm_opcode_defs 0.131.0", ] [[package]] name = "zk_evm" -version = "1.3.3" -source = "git+https://github.com/matter-labs/era-zk_evm.git?branch=v1.3.3#fbee20f5bac7d6ca3e22ae69b2077c510a07de4e" +version = "0.133.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9af08e9284686a1b0c89ec4931eb915ac0729367f1247abd06164874fe738106" dependencies = [ "anyhow", "lazy_static", @@ -5724,14 +6171,15 @@ dependencies = [ "serde", "serde_json", "static_assertions", - "zk_evm_abstractions 0.1.0", - "zkevm_opcode_defs 1.3.2", + "zk_evm_abstractions 0.140.0", + "zkevm_opcode_defs 0.132.0", ] [[package]] name = "zk_evm" -version = "1.4.0" -source = "git+https://github.com/matter-labs/era-zk_evm.git?branch=v1.4.0#dd76fc5badf2c05278a21b38015a7798fe2fe358" +version = "0.140.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349bb8320d12578537658792df708f43c52e6330f0df071f812cb93b04ade962" dependencies = [ "anyhow", "lazy_static", @@ -5739,14 +6187,15 @@ dependencies = [ "serde", "serde_json", "static_assertions", - "zk_evm_abstractions 0.1.0", - "zkevm_opcode_defs 1.3.2", + "zk_evm_abstractions 0.140.0", + "zkevm_opcode_defs 0.132.0", ] [[package]] name = "zk_evm" -version = "1.4.1" -source = "git+https://github.com/matter-labs/era-zk_evm.git?branch=v1.4.1#6250dbf64b2d14ced87a127735da559f27a432d5" +version = "0.141.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8886ba5989b952b7b76096469eeb6fdfaf3369770e9e22a6f67dc4b7d65f9243" dependencies = [ "anyhow", "lazy_static", @@ -5754,14 +6203,15 @@ dependencies = [ "serde", "serde_json", "static_assertions", - "zk_evm_abstractions 1.4.1", - "zkevm_opcode_defs 1.4.1", + "zk_evm_abstractions 0.141.0", + "zkevm_opcode_defs 0.141.0", ] [[package]] name = "zk_evm" -version = "1.5.0" -source = "git+https://github.com/matter-labs/era-zk_evm.git?branch=v1.5.0#0448e26ffd8e2f1935ff8cd3303fe5a504cd5d7b" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6e69931f24db5cf333b714721e8d80ff88bfdb7da8c3dc7882612ffddb8d27" dependencies = [ "anyhow", "lazy_static", @@ -5769,54 +6219,57 @@ dependencies = [ "serde", "serde_json", "static_assertions", - "zk_evm_abstractions 1.5.0", + "zk_evm_abstractions 0.150.5", ] [[package]] name = "zk_evm_abstractions" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-zk_evm_abstractions.git#32dd320953841aa78579d9da08abbc70bcaed175" +version = "0.140.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be696258861eba4e6625a5665084b2266720bb67f4ba69819469700ac5c6a401" dependencies = [ "anyhow", "num_enum 0.6.1", "serde", "static_assertions", - "zkevm_opcode_defs 1.3.2", + "zkevm_opcode_defs 0.132.0", ] [[package]] name = "zk_evm_abstractions" -version = "1.4.1" -source = "git+https://github.com/matter-labs/era-zk_evm_abstractions.git?branch=v1.4.1#0aac08c3b097ee8147e748475117ac46bddcdcef" +version = "0.141.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637a3cb6cb475bb238bee3e450763205d36fe6c92dc1b23300655927915baf03" dependencies = [ "anyhow", "num_enum 0.6.1", "serde", "static_assertions", - "zkevm_opcode_defs 1.4.1", + "zkevm_opcode_defs 0.141.0", ] [[package]] name = "zk_evm_abstractions" -version = "1.5.0" -source = "git+https://github.com/matter-labs/era-zk_evm_abstractions.git?branch=v1.5.0#e464b2cf2b146d883be80e7d690c752bf670ff05" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6b0720261ab55490fe3a96e96de30d5d7b277940b52ea7f52dbf564eb1748" dependencies = [ "anyhow", "num_enum 0.6.1", "serde", "static_assertions", - "zkevm_opcode_defs 1.5.0", + "zkevm_opcode_defs 0.150.5", ] [[package]] name = "zkevm_circuits" -version = "1.4.0" -source = "git+https://github.com/matter-labs/era-zkevm_circuits.git?branch=v1.4.0#fb3e2574b5c890342518fc930c145443f039a105" +version = "0.140.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c365c801e0c6eda83fbd153df45575172beb406bfb663d386f9154b4325eda" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bincode", "boojum", - "cs_derive", "derivative", "hex", "itertools 0.10.5", @@ -5826,18 +6279,19 @@ dependencies = [ "serde", "serde_json", "smallvec", - "zkevm_opcode_defs 1.3.2", + "zkevm_opcode_defs 0.132.0", + "zksync_cs_derive", ] [[package]] name = "zkevm_circuits" -version = "1.4.1" -source = "git+https://github.com/matter-labs/era-zkevm_circuits.git?branch=v1.4.1#8bf24543ffc5bafab34182388394e887ecb37d17" +version = "0.141.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ccd0352e122a4e6f0046d2163b7e692e627b23fc3264faa77331a21b65833fd" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "bincode", "boojum", - "cs_derive", "derivative", "hex", "itertools 0.10.5", @@ -5847,17 +6301,18 @@ dependencies = [ "serde", "serde_json", "smallvec", - "zkevm_opcode_defs 1.4.1", + "zkevm_opcode_defs 0.141.0", + "zksync_cs_derive", ] [[package]] name = "zkevm_circuits" -version = "1.5.0" -source = "git+https://github.com/matter-labs/era-zkevm_circuits.git?branch=v1.5.0#861f81029bf3a916dae55afa5bd7f82b2eaca98b" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784fa7cfb51e17c5ced112bca43da30b3468b2347b7af0427ad9638759fb140e" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "boojum", - "cs_derive", "derivative", "hex", "itertools 0.10.5", @@ -5866,13 +6321,15 @@ dependencies = [ "seq-macro", "serde", "smallvec", - "zkevm_opcode_defs 1.5.0", + "zkevm_opcode_defs 0.150.5", + "zksync_cs_derive", ] [[package]] name = "zkevm_opcode_defs" -version = "1.3.1" -source = "git+https://github.com/matter-labs/era-zkevm_opcode_defs.git?branch=v1.3.1#00d4ad2292bd55374a0fa10fe11686d7a109d8a0" +version = "0.131.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e0154bd4ae8202c96c52b29dd44f944bfd08c1c233fef843744463964de957" dependencies = [ "bitflags 1.3.2", "ethereum-types", @@ -5882,27 +6339,29 @@ dependencies = [ [[package]] name = "zkevm_opcode_defs" -version = "1.3.2" -source = "git+https://github.com/matter-labs/era-zkevm_opcode_defs.git?branch=v1.3.2#dffacadeccdfdbff4bc124d44c595c4a6eae5013" +version = "0.132.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0769f7b27d8fb06e715da3290c575cac5d04d10a557faef180e847afce50ac4" dependencies = [ - "bitflags 2.4.1", - "blake2 0.10.6 (git+https://github.com/RustCrypto/hashes.git?rev=1f727ce37ff40fa0cce84eb8543a45bdd3ca4a4e)", + "bitflags 2.6.0", + "blake2 0.10.6", "ethereum-types", "k256 0.11.6", "lazy_static", - "sha2 0.10.6", - "sha3 0.10.6", + "sha2_ce", + "sha3_ce", ] [[package]] name = "zkevm_opcode_defs" -version = "1.4.1" -source = "git+https://github.com/matter-labs/era-zkevm_opcode_defs.git?branch=v1.4.1#ba8228ff0582d21f64d6a319d50d0aec48e9e7b6" +version = "0.141.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6be7bd5f0e0b61211f544147289640b4712715589d7f2fe5229d92a7a3ac64c0" dependencies = [ - "bitflags 2.4.1", - "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.6.0", + "blake2 0.10.6", "ethereum-types", - "k256 0.13.3", + "k256 0.13.4", "lazy_static", "sha2 0.10.8", "sha3 0.10.8", @@ -5910,13 +6369,14 @@ dependencies = [ [[package]] name = "zkevm_opcode_defs" -version = "1.5.0" -source = "git+https://github.com/matter-labs/era-zkevm_opcode_defs.git?branch=v1.5.0#109d9f734804a8b9dc0531c0b576e2a0f55a40de" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79055eae1b6c1ab80793ed9d77d2964c9c896afa4b5dfed278cf58cd10acfe8f" dependencies = [ - "bitflags 2.4.1", - "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.6.0", + "blake2 0.10.6", "ethereum-types", - "k256 0.13.3", + "k256 0.13.4", "lazy_static", "p256", "serde", @@ -5927,20 +6387,51 @@ dependencies = [ [[package]] name = "zksync_basic_types" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ + "anyhow", "chrono", - "num_enum 0.7.2", + "ethabi", + "hex", + "num_enum 0.7.3", + "secrecy", "serde", "serde_json", + "serde_with", "strum", - "web3", + "thiserror", + "tiny-keccak 2.0.2", + "url", +] + +[[package]] +name = "zksync_bellman" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffa03efe9bdb137a4b36b97d1a74237e18c9ae42b755163d903a9d48c1a5d80" +dependencies = [ + "arrayvec 0.7.6", + "bit-vec", + "blake2s_simd", + "byteorder", + "cfg-if", + "crossbeam", + "futures", + "hex", + "lazy_static", + "num_cpus", + "rand 0.4.6", + "serde", + "smallvec", + "tiny-keccak 1.5.0", + "zksync_pairing", ] [[package]] name = "zksync_concurrency" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "035269d811b3770debca372141ab64cad067dce8e58cb39a48cb7617d30c626b" dependencies = [ "anyhow", "once_cell", @@ -5958,43 +6449,55 @@ dependencies = [ [[package]] name = "zksync_config" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", "rand 0.8.5", + "secrecy", "serde", + "strum", + "strum_macros", + "time", + "url", + "vise", "zksync_basic_types", + "zksync_concurrency", "zksync_consensus_utils", "zksync_crypto_primitives", ] [[package]] name = "zksync_consensus_crypto" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e38d1b5ed28c66e785caff53ea4863375555d818aafa03290397192dd3e665" dependencies = [ "anyhow", "blst", "ed25519-dalek", - "ff_ce", + "elliptic-curve 0.13.8", "hex", - "pairing_ce 0.28.5 (git+https://github.com/matter-labs/pairing.git?rev=d24f2c5871089c4cd4f54c0ca266bb9fef6115eb)", - "rand 0.4.6", + "k256 0.13.4", + "num-bigint 0.4.6", + "num-traits", "rand 0.8.5", "sha3 0.10.8", "thiserror", "tracing", + "zeroize", ] [[package]] name = "zksync_consensus_roles" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e49fbd4e69b276058f3dfc06cf6ada0e8caa6ed826e81289e4d596da95a0f17a" dependencies = [ "anyhow", "bit-vec", "hex", - "prost 0.12.3", + "num-bigint 0.4.6", + "prost 0.12.6", "rand 0.8.5", "serde", "thiserror", @@ -6008,17 +6511,19 @@ dependencies = [ [[package]] name = "zksync_consensus_storage" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b2aab4ed18b13cd584f4edcc2546c8da82f89ac62e525063e12935ff28c9be" dependencies = [ "anyhow", "async-trait", - "prost 0.12.3", + "prost 0.12.6", "rand 0.8.5", "thiserror", "tracing", "vise", "zksync_concurrency", + "zksync_consensus_crypto", "zksync_consensus_roles", "zksync_protobuf", "zksync_protobuf_build", @@ -6026,9 +6531,11 @@ dependencies = [ [[package]] name = "zksync_consensus_utils" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10bac8f471b182d4fa3d40cf158aac3624fe636a1ff0b4cf3fe26a0e20c68a42" dependencies = [ + "anyhow", "rand 0.8.5", "thiserror", "zksync_concurrency", @@ -6037,7 +6544,7 @@ dependencies = [ [[package]] name = "zksync_contracts" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "envy", "ethabi", @@ -6048,40 +6555,40 @@ dependencies = [ "zksync_utils", ] -[[package]] -name = "zksync_crypto" -version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" -dependencies = [ - "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", - "hex", - "once_cell", - "serde", - "sha2 0.10.8", - "thiserror", - "zksync_basic_types", -] - [[package]] name = "zksync_crypto_primitives" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", + "blake2 0.10.6", "hex", + "rand 0.8.5", "secp256k1", "serde", "serde_json", + "sha2 0.10.8", "thiserror", - "web3", "zksync_basic_types", "zksync_utils", ] +[[package]] +name = "zksync_cs_derive" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5939e2df4288c263c706ff18ac718e984149223ad4289d6d957d767dcfc04c81" +dependencies = [ + "proc-macro-error", + "proc-macro2 1.0.87", + "quote 1.0.37", + "syn 1.0.109", +] + [[package]] name = "zksync_dal" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", "bigdecimal", @@ -6089,7 +6596,7 @@ dependencies = [ "chrono", "hex", "itertools 0.10.5", - "prost 0.12.3", + "prost 0.12.6", "rand 0.8.5", "serde", "serde_json", @@ -6099,21 +6606,26 @@ dependencies = [ "tokio", "tracing", "vise", + "zksync_concurrency", + "zksync_consensus_crypto", "zksync_consensus_roles", "zksync_consensus_storage", + "zksync_consensus_utils", "zksync_contracts", "zksync_db_connection", + "zksync_l1_contract_interface", "zksync_protobuf", "zksync_protobuf_build", "zksync_system_constants", "zksync_types", "zksync_utils", + "zksync_vm_interface", ] [[package]] name = "zksync_db_connection" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", "rand 0.8.5", @@ -6123,45 +6635,159 @@ dependencies = [ "thiserror", "tokio", "tracing", - "url", "vise", - "zksync_health_check", + "zksync_basic_types", ] [[package]] -name = "zksync_health_check" -version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +name = "zksync_ff" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9524b06780b5e164e84b38840c7c428c739f051f35af6efc4d1285f629ceb88e" dependencies = [ - "async-trait", - "futures", + "byteorder", + "hex", + "rand 0.4.6", + "serde", + "zksync_ff_derive", +] + +[[package]] +name = "zksync_ff_derive" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f91e58e75d65877f09f83bc3dca8f054847ae7ec4f3e64bfa610a557edd8e8e" +dependencies = [ + "num-bigint 0.4.6", + "num-integer", + "num-traits", + "proc-macro2 1.0.87", + "quote 1.0.37", + "serde", + "syn 1.0.109", +] + +[[package]] +name = "zksync_kzg" +version = "0.150.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb8a9c76c172a6d639855ee342b9a670e3ba472f5ae302f771b1c3ee777dc88" +dependencies = [ + "boojum", + "derivative", + "hex", + "once_cell", + "rayon", "serde", "serde_json", - "thiserror", - "tokio", - "tracing", - "vise", + "serde_with", + "zkevm_circuits 0.150.5", +] + +[[package]] +name = "zksync_l1_contract_interface" +version = "0.1.0" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "anyhow", + "hex", + "once_cell", + "sha2 0.10.8", + "sha3 0.10.8", + "zksync_kzg", + "zksync_prover_interface", + "zksync_solidity_vk_codegen", + "zksync_types", ] [[package]] name = "zksync_mini_merkle_tree" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "once_cell", "zksync_basic_types", - "zksync_crypto", + "zksync_crypto_primitives", ] [[package]] -name = "zksync_protobuf" +name = "zksync_multivm" +version = "0.1.0" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "anyhow", + "circuit_sequencer_api 0.133.1", + "circuit_sequencer_api 0.140.3", + "circuit_sequencer_api 0.141.2", + "circuit_sequencer_api 0.142.2", + "circuit_sequencer_api 0.150.5", + "ethabi", + "hex", + "itertools 0.10.5", + "once_cell", + "thiserror", + "tracing", + "vise", + "zk_evm 0.131.0-rc.2", + "zk_evm 0.133.0", + "zk_evm 0.140.0", + "zk_evm 0.141.0", + "zk_evm 0.150.5", + "zksync_contracts", + "zksync_system_constants", + "zksync_types", + "zksync_utils", + "zksync_vm2", + "zksync_vm_interface", +] + +[[package]] +name = "zksync_object_store" version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "flate2", + "google-cloud-auth", + "google-cloud-storage", + "http 1.1.0", + "prost 0.12.6", + "rand 0.8.5", + "reqwest 0.12.8", + "serde_json", + "tokio", + "tracing", + "vise", + "zksync_config", + "zksync_protobuf", + "zksync_types", +] + +[[package]] +name = "zksync_pairing" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8412ae5574472fa567a097e183f9a01974b99dd0b5da3bfa1bbe6c57c579aa2" +dependencies = [ + "byteorder", + "cfg-if", + "rand 0.4.6", + "serde", + "zksync_ff", +] + +[[package]] +name = "zksync_protobuf" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abd55c64f54cb10967a435422f66ff5880ae14a232b245517c7ce38da32e0cab" dependencies = [ "anyhow", "bit-vec", "once_cell", - "prost 0.12.3", + "prost 0.12.6", "prost-reflect", "quick-protobuf", "rand 0.8.5", @@ -6175,37 +6801,73 @@ dependencies = [ [[package]] name = "zksync_protobuf_build" -version = "0.1.0" -source = "git+https://github.com/matter-labs/era-consensus.git?rev=1dcda70c1c25d0e4db6781ba8d2645d7e8966d49#1dcda70c1c25d0e4db6781ba8d2645d7e8966d49" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4121952bcaf711005dd554612fc6e2de9b30cb58088508df87f1d38046ce8ac8" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "prettyplease", - "proc-macro2", + "proc-macro2 1.0.87", "prost-build", "prost-reflect", "protox", - "quote", - "syn 2.0.40", + "quote 1.0.37", + "syn 2.0.79", +] + +[[package]] +name = "zksync_prover_interface" +version = "0.1.0" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "chrono", + "circuit_sequencer_api 0.150.5", + "serde", + "serde_with", + "strum", + "zksync_multivm", + "zksync_object_store", + "zksync_types", ] [[package]] name = "zksync_shared_metrics" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ + "rustc_version", + "tracing", "vise", "zksync_dal", "zksync_types", ] +[[package]] +name = "zksync_solidity_vk_codegen" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b310ab8a21681270e73f177ddf7974cabb7a96f0624ab8b008fd6ee1f9b4f687" +dependencies = [ + "ethereum-types", + "franklin-crypto", + "handlebars", + "hex", + "paste", + "rescue_poseidon", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "zksync_state" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", "async-trait", + "backon", "chrono", "itertools 0.10.5", "mini-moka", @@ -6218,12 +6880,13 @@ dependencies = [ "zksync_storage", "zksync_types", "zksync_utils", + "zksync_vm_interface", ] [[package]] name = "zksync_storage" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "num_cpus", "once_cell", @@ -6236,7 +6899,7 @@ dependencies = [ [[package]] name = "zksync_system_constants" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "once_cell", "zksync_basic_types", @@ -6246,24 +6909,27 @@ dependencies = [ [[package]] name = "zksync_types" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", - "blake2 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bigdecimal", + "blake2 0.10.6", "chrono", - "derive_more 1.0.0-beta.6", + "derive_more", "hex", "itertools 0.10.5", "num", - "num_enum 0.7.2", + "num_enum 0.7.3", "once_cell", - "prost 0.12.3", + "prost 0.12.6", "rlp", "secp256k1", "serde", "serde_json", + "serde_with", "strum", "thiserror", + "tracing", "zksync_basic_types", "zksync_config", "zksync_contracts", @@ -6278,29 +6944,93 @@ dependencies = [ [[package]] name = "zksync_utils" version = "0.1.0" -source = "git+https://github.com/matter-labs/zksync-era.git?rev=c4d1c49282a3710be5d491636ba26207efb1f9ce#c4d1c49282a3710be5d491636ba26207efb1f9ce" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" dependencies = [ "anyhow", "bigdecimal", "futures", "hex", - "itertools 0.10.5", "num", - "reqwest", + "once_cell", + "reqwest 0.12.8", "serde", + "serde_json", "thiserror", "tokio", "tracing", - "vlog", - "zk_evm 1.3.3 (git+https://github.com/matter-labs/era-zk_evm.git?tag=v1.3.3-rc2)", + "zk_evm 0.133.0", "zksync_basic_types", + "zksync_vlog", +] + +[[package]] +name = "zksync_vlog" +version = "0.1.0" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "anyhow", + "chrono", + "opentelemetry", + "opentelemetry-appender-tracing", + "opentelemetry-otlp", + "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "sentry", + "serde", + "serde_json", + "thiserror", + "time", + "tokio", + "tracing", + "tracing-opentelemetry", + "tracing-subscriber", + "url", + "vise", + "vise-exporter", +] + +[[package]] +name = "zksync_vm2" +version = "0.2.1" +source = "git+https://github.com/matter-labs/vm2.git?rev=a233d44bbe61dc6a758a754c3b78fe4f83e56699#a233d44bbe61dc6a758a754c3b78fe4f83e56699" +dependencies = [ + "enum_dispatch", + "primitive-types", + "zk_evm_abstractions 0.150.5", + "zkevm_opcode_defs 0.150.5", + "zksync_vm2_interface", +] + +[[package]] +name = "zksync_vm2_interface" +version = "0.2.1" +source = "git+https://github.com/matter-labs/vm2.git?rev=a233d44bbe61dc6a758a754c3b78fe4f83e56699#a233d44bbe61dc6a758a754c3b78fe4f83e56699" +dependencies = [ + "primitive-types", +] + +[[package]] +name = "zksync_vm_interface" +version = "0.1.0" +source = "git+https://github.com/matter-labs/zksync-era.git?rev=c1ab99d8d72509ccb9a537025cc6df9df141dd96#c1ab99d8d72509ccb9a537025cc6df9df141dd96" +dependencies = [ + "anyhow", + "async-trait", + "hex", + "pretty_assertions", + "serde", + "thiserror", + "tracing", + "zksync_contracts", + "zksync_system_constants", + "zksync_types", ] [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/system-contracts/bootloader/test_infra/Cargo.toml b/system-contracts/bootloader/test_infra/Cargo.toml index cfcd2c9a3..8ca71ef8a 100644 --- a/system-contracts/bootloader/test_infra/Cargo.toml +++ b/system-contracts/bootloader/test_infra/Cargo.toml @@ -7,12 +7,12 @@ edition = "2021" [dependencies] -multivm = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } -zksync_types = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } -zksync_contracts = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } -zksync_utils = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } -zksync_state = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } -vlog = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c4d1c49282a3710be5d491636ba26207efb1f9ce" } +zksync_multivm = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } +zksync_types = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } +zksync_contracts = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } +zksync_utils = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } +zksync_state = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } +zksync_vlog = { git = "https://github.com/matter-labs/zksync-era.git", rev = "c1ab99d8d72509ccb9a537025cc6df9df141dd96" } colored = "2.0" hex = "0.4" diff --git a/system-contracts/bootloader/test_infra/rust-toolchain b/system-contracts/bootloader/test_infra/rust-toolchain index 9a87fb21c..226a309c8 100644 --- a/system-contracts/bootloader/test_infra/rust-toolchain +++ b/system-contracts/bootloader/test_infra/rust-toolchain @@ -1 +1 @@ -nightly-2023-08-21 +nightly-2024-08-01 \ No newline at end of file diff --git a/system-contracts/bootloader/test_infra/src/hook.rs b/system-contracts/bootloader/test_infra/src/hook.rs index 04bacc90c..b1f0f1078 100644 --- a/system-contracts/bootloader/test_infra/src/hook.rs +++ b/system-contracts/bootloader/test_infra/src/hook.rs @@ -1,9 +1,9 @@ -use multivm::vm_latest::{ - constants::{BOOTLOADER_HEAP_PAGE, get_vm_hook_start_position_latest}, +use zksync_multivm::vm_latest::{ + constants::{get_vm_hook_start_position_latest, BOOTLOADER_HEAP_PAGE}, HistoryMode, SimpleMemory, }; -use multivm::zk_evm_latest::{ +use zksync_multivm::zk_evm_latest::{ aux_structures::MemoryPage, tracing::{BeforeExecutionData, VmLocalStateData}, zkevm_opcode_defs::{FatPointer, Opcode, UMAOpcode}, diff --git a/system-contracts/bootloader/test_infra/src/main.rs b/system-contracts/bootloader/test_infra/src/main.rs index 3928200e4..4e55b0ed3 100644 --- a/system-contracts/bootloader/test_infra/src/main.rs +++ b/system-contracts/bootloader/test_infra/src/main.rs @@ -1,25 +1,25 @@ use crate::{test_count_tracer::TestCountTracer, tracer::BootloaderTestTracer}; use colored::Colorize; -use multivm::interface::{ - L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode, VmExecutionMode, VmInterface, -}; -use multivm::vm_latest::{HistoryDisabled, ToTracerPointer, Vm}; use once_cell::sync::OnceCell; -use zksync_types::fee_model::BatchFeeInput; use std::process; +use zksync_multivm::interface::{ + L1BatchEnv, L2BlockEnv, SystemEnv, TxExecutionMode, VmExecutionMode, VmFactory, VmInterface, +}; +use zksync_multivm::vm_latest::{HistoryDisabled, ToTracerPointer, TracerDispatcher, Vm}; +use zksync_state::interface::{ + InMemoryStorage, StoragePtr, StorageView, IN_MEMORY_STORAGE_DEFAULT_NETWORK_ID, +}; +use zksync_types::fee_model::BatchFeeInput; -use multivm::interface::{ExecutionResult, Halt}; use std::{env, sync::Arc}; use tracing_subscriber::fmt; use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use zksync_contracts::{ - read_zbin_bytecode, BaseSystemContracts, ContractLanguage, SystemContractCode, + read_yul_bytecode, BaseSystemContracts, ContractLanguage, SystemContractCode, SystemContractsRepo, }; -use zksync_state::{ - InMemoryStorage, StoragePtr, StorageView, IN_MEMORY_STORAGE_DEFAULT_NETWORK_ID, -}; +use zksync_multivm::interface::{ExecutionResult, Halt}; use zksync_types::system_contracts::get_system_smart_contracts_from_dir; use zksync_types::{block::L2BlockHasher, Address, L1BatchNumber, L2BlockNumber, U256}; use zksync_types::{L2ChainId, Transaction}; @@ -32,11 +32,13 @@ mod tracer; // Executes bootloader unittests. fn execute_internal_bootloader_test() { - let test_location = env::current_dir() - .unwrap() - .join("../build/artifacts/bootloader_test.yul.zbin"); - println!("Current dir is {:?}", test_location); - let bytecode = read_zbin_bytecode(test_location.as_path()); + let artifacts_location_path = env::current_dir().unwrap().join("../build/artifacts"); + let artifacts_location = artifacts_location_path + .to_str() + .expect("Invalid path: {artifacts_location_path:?}"); + println!("Current dir is {:?}", artifacts_location); + + let bytecode = read_yul_bytecode(artifacts_location, "bootloader_test"); let hash = hash_bytecode(&bytecode); let bootloader = SystemContractCode { code: bytes_to_be_words(bytecode), @@ -57,6 +59,7 @@ fn execute_internal_bootloader_test() { let base_system_contract = BaseSystemContracts { bootloader, default_aa, + evm_emulator: None, }; let system_env = SystemEnv { @@ -91,19 +94,23 @@ fn execute_internal_bootloader_test() { StorageView::new(InMemoryStorage::with_custom_system_contracts_and_chain_id( L2ChainId::from(IN_MEMORY_STORAGE_DEFAULT_NETWORK_ID), hash_bytecode, - get_system_smart_contracts_from_dir(env::current_dir().unwrap().join("../../")), + get_system_smart_contracts_from_dir( + env::current_dir().unwrap().join("../../"), + false, + ), )) .to_rc_ptr(); let mut vm: Vm<_, HistoryDisabled> = - Vm::new(l1_batch_env.clone(), system_env.clone(), storage.clone()); + VmFactory::new(l1_batch_env.clone(), system_env.clone(), storage.clone()); let test_count = Arc::new(OnceCell::default()); let custom_tracers = TestCountTracer::new(test_count.clone()).into_tracer_pointer(); // We're using a TestCountTracer (and passing 0 as fee account) - this should cause the bootloader // test framework to report number of tests via VM hook. - vm.inspect(custom_tracers.into(), VmExecutionMode::Bootloader); + let mut tracer_dispatcher = TracerDispatcher::from(custom_tracers); + vm.inspect(&mut tracer_dispatcher, VmExecutionMode::Bootloader); test_count.get().unwrap().clone() }; @@ -119,7 +126,10 @@ fn execute_internal_bootloader_test() { StorageView::new(InMemoryStorage::with_custom_system_contracts_and_chain_id( L2ChainId::from(IN_MEMORY_STORAGE_DEFAULT_NETWORK_ID), hash_bytecode, - get_system_smart_contracts_from_dir(env::current_dir().unwrap().join("../../")), + get_system_smart_contracts_from_dir( + env::current_dir().unwrap().join("../../"), + false, + ), )) .to_rc_ptr(); @@ -138,13 +148,16 @@ fn execute_internal_bootloader_test() { test_name.clone(), ) .into_tracer_pointer(); + let mut tracer_dispatcher = TracerDispatcher::from(custom_tracers); // Let's insert transactions into slots. They are not executed, but the tests can run functions against them. let json_str = include_str!("test_transactions/0.json"); let tx: Transaction = serde_json::from_str(json_str).unwrap(); vm.push_transaction(tx); - let result = vm.inspect(custom_tracers.into(), VmExecutionMode::Bootloader); + let result = vm.inspect(&mut tracer_dispatcher, VmExecutionMode::Bootloader); + drop(tracer_dispatcher); + let mut test_result = Arc::into_inner(test_result).unwrap().into_inner(); let requested_assert = Arc::into_inner(requested_assert).unwrap().into_inner(); let test_name = Arc::into_inner(test_name) diff --git a/system-contracts/bootloader/test_infra/src/test_count_tracer.rs b/system-contracts/bootloader/test_infra/src/test_count_tracer.rs index 1c2dfa523..f82a4df6a 100644 --- a/system-contracts/bootloader/test_infra/src/test_count_tracer.rs +++ b/system-contracts/bootloader/test_infra/src/test_count_tracer.rs @@ -1,10 +1,10 @@ use std::sync::Arc; -use multivm::interface::dyn_tracers::vm_1_5_0::DynTracer; -use multivm::vm_latest::{HistoryMode, SimpleMemory, VmTracer}; -use multivm::zk_evm_latest::tracing::{BeforeExecutionData, VmLocalStateData}; use once_cell::sync::OnceCell; -use zksync_state::{StoragePtr, WriteStorage}; +use zksync_multivm::tracers::dynamic::vm_1_5_0::DynTracer; +use zksync_multivm::vm_latest::{HistoryMode, SimpleMemory, VmTracer}; +use zksync_multivm::zk_evm_latest::tracing::{BeforeExecutionData, VmLocalStateData}; +use zksync_state::interface::{StoragePtr, WriteStorage}; use crate::hook::TestVmHook; diff --git a/system-contracts/bootloader/test_infra/src/tracer.rs b/system-contracts/bootloader/test_infra/src/tracer.rs index c38875235..8b26cba35 100644 --- a/system-contracts/bootloader/test_infra/src/tracer.rs +++ b/system-contracts/bootloader/test_infra/src/tracer.rs @@ -3,14 +3,15 @@ use std::sync::Arc; use colored::Colorize; use once_cell::sync::OnceCell; -use multivm::interface::{ - dyn_tracers::vm_1_5_0::DynTracer, - tracer::{TracerExecutionStatus, TracerExecutionStopReason}, +use zksync_multivm::tracers::dynamic::vm_1_5_0::DynTracer; + +use zksync_multivm::interface::tracer::{TracerExecutionStatus, TracerExecutionStopReason}; +use zksync_multivm::vm_latest::{ + BootloaderState, HistoryMode, SimpleMemory, VmTracer, ZkSyncVmState, }; -use multivm::vm_latest::{BootloaderState, HistoryMode, SimpleMemory, VmTracer, ZkSyncVmState}; -use multivm::zk_evm_latest::tracing::{BeforeExecutionData, VmLocalStateData}; +use zksync_multivm::zk_evm_latest::tracing::{BeforeExecutionData, VmLocalStateData}; -use zksync_state::{StoragePtr, WriteStorage}; +use zksync_state::interface::{StoragePtr, WriteStorage}; use crate::hook::TestVmHook; diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol index 556852160..dab8c4834 100644 --- a/system-contracts/contracts/EvmGasManager.sol +++ b/system-contracts/contracts/EvmGasManager.sol @@ -50,7 +50,7 @@ contract EvmGasManager { // This error should never happen revert(0, 0) } - + rawCodeHash := mload(0) } diff --git a/system-contracts/contracts/test-contracts/ExtraAbiCaller.zasm b/system-contracts/contracts/test-contracts/ExtraAbiCaller.zasm index b95b2a08b..30ed1d9f8 100644 --- a/system-contracts/contracts/test-contracts/ExtraAbiCaller.zasm +++ b/system-contracts/contracts/test-contracts/ExtraAbiCaller.zasm @@ -4,14 +4,14 @@ __entry: .func_begin0: sub.s! 0, r2, r0 - jump.eq @.RUNTIME_CODE + jump.eq @RUNTIME_CODE ; deployment code add 32, r0, r1 - st.1 r0, r1 - st.1 r1, r0 - add @CPI0_1[0], r0, r1 - ret.ok.to_label r1, @DEFAULT_FAR_RETURN -.RUNTIME_CODE: + stm.h r0, r1 + stm.h r1, r0 + add code[@CPI0_1], r0, r1 + retl r1, @DEFAULT_FAR_RETURN +RUNTIME_CODE: ; ABI: ; 0-32 address(in the lowest 20 bytes) ; 32-64 msg.value @@ -19,29 +19,31 @@ __entry: ; 384+ calldata ; ; load address into r2 - ld.inc r1, r2, r1 + ldpi r1, r2, r1 ; set msg.value - ld.inc r1, r3, r1 - context.set_context_u128 r3 + ldpi r1, r3, r1 + stvl r3 ; load extra abi data into r3-r12 - ld.inc r1, r3, r1 - ld.inc r1, r4, r1 - ld.inc r1, r5, r1 - ld.inc r1, r6, r1 - ld.inc r1, r7, r1 - ld.inc r1, r8, r1 - ld.inc r1, r9, r1 - ld.inc r1, r10, r1 - ld.inc r1, r11, r1 - ld.inc r1, r12, r1 - ptr.pack.s @CPI0_0[0], r1, r1 - far_call r1, r2, @.CALL_REVERT - ptr.pack.s @CPI0_2[0], r1, r1 - ret.ok r1 + ldpi r1, r3, r1 + ldpi r1, r4, r1 + ldpi r1, r5, r1 + ldpi r1, r6, r1 + ldpi r1, r7, r1 + ldpi r1, r8, r1 + ldpi r1, r9, r1 + ldpi r1, r10, r1 + ldpi r1, r11, r1 + ldpi r1, r12, r1 + pack.s code[@CPI0_0], r1, r1 + callf r1, r2, @.CALL_REVERT + pack.s code[@CPI0_2], r1, r1 + ret r1 .CALL_REVERT: - ptr.pack.s @CPI0_2[0], r1, r1 - ret.revert r1 + pack.s code[@CPI0_2], r1, r1 + rev r1 .func_end0: +DEFAULT_FAR_RETURN: + retl @DEFAULT_FAR_RETURN .note.GNU-stack .rodata ; far call abi: @@ -57,4 +59,4 @@ CPI0_1: .cell 5070602400912917605986812821504 ; 01 00000000 0000000000000000 00000000000000000000000000000000 CPI0_2: - .cell 26959946667150639794667015087019630673637144422540572481103610249216 + .cell 26959946667150639794667015087019630673637144422540572481103610249216 \ No newline at end of file diff --git a/system-contracts/foundry.toml b/system-contracts/foundry.toml index ee3885489..748734ad6 100644 --- a/system-contracts/foundry.toml +++ b/system-contracts/foundry.toml @@ -10,4 +10,4 @@ remappings = [ ] [profile.default.zksync] -zksolc = "1.5.0" +zksolc = "1.5.4" diff --git a/system-contracts/hardhat.config.ts b/system-contracts/hardhat.config.ts index 7ad59a41f..5a6ab2986 100644 --- a/system-contracts/hardhat.config.ts +++ b/system-contracts/hardhat.config.ts @@ -6,8 +6,8 @@ import "@nomiclabs/hardhat-ethers"; import "hardhat-typechain"; // This version of system contracts requires a pre release of the compiler -const COMPILER_VERSION = "1.5.0"; -const PRE_RELEASE_VERSION = "prerelease-a167aa3-code4rena"; +const COMPILER_VERSION = "v1.5.6"; +const PRE_RELEASE_VERSION = "1.5.6"; function getZksolcUrl(): string { // @ts-ignore const platform = { darwin: "macosx", linux: "linux", win32: "windows" }[process.platform]; @@ -16,7 +16,7 @@ function getZksolcUrl(): string { const arch = process.arch === "x64" ? "amd64" : process.arch; const ext = process.platform === "win32" ? ".exe" : ""; - return `https://github.com/matter-labs/era-compiler-solidity/releases/download/${PRE_RELEASE_VERSION}/zksolc-${platform}-${arch}${toolchain}-v${COMPILER_VERSION}${ext}`; + return `https://github.com/matter-labs/era-compiler-solidity/releases/download/${PRE_RELEASE_VERSION}/zksolc-${platform}-${arch}${toolchain}-${COMPILER_VERSION}${ext}`; } console.log(`Using zksolc from ${getZksolcUrl()}`); @@ -26,7 +26,8 @@ export default { compilerSource: "binary", settings: { compilerPath: getZksolcUrl(), - isSystem: true, + enableEraVMExtensions: true, + suppressedErrors: ["sendtransfer"], }, }, zkSyncDeploy: { diff --git a/system-contracts/package.json b/system-contracts/package.json index e4b97d4ee..27b5ee5e3 100644 --- a/system-contracts/package.json +++ b/system-contracts/package.json @@ -5,7 +5,7 @@ "license": "MIT", "dependencies": { "@matterlabs/hardhat-zksync-deploy": "^0.7.0", - "@matterlabs/hardhat-zksync-solc": "^1.1.4", + "@matterlabs/hardhat-zksync-solc": "^1.2.5", "@matterlabs/hardhat-zksync-verify": "^1.4.3", "commander": "^9.4.1", "eslint": "^8.51.0", diff --git a/system-contracts/scripts/calculate-hashes.ts b/system-contracts/scripts/calculate-hashes.ts index a8fc8036f..e63c3abf8 100644 --- a/system-contracts/scripts/calculate-hashes.ts +++ b/system-contracts/scripts/calculate-hashes.ts @@ -65,7 +65,7 @@ const getSolidityContractsDetails = (dir: string): ContractDetails[] => { const YUL_ARTIFACTS_DIR = "artifacts"; const getYulContractDetails = (dir: string, contractName: string): ContractDetails => { - const bytecodePath = join(dir, YUL_ARTIFACTS_DIR, contractName + ".yul.zbin"); + const bytecodePath = join(dir, YUL_ARTIFACTS_DIR, contractName + ".yul", contractName + ".yul.zbin"); const sourceCodePath = join(dir, contractName + ".yul"); return { contractName, @@ -102,7 +102,7 @@ const readBytecode = (details: ContractDetails): string => { const jsonFile = fs.readFileSync(absolutePath, "utf8"); return ethers.utils.hexlify(JSON.parse(jsonFile).bytecode); } else { - return ethers.utils.hexlify(fs.readFileSync(absolutePath)); + return ethers.utils.hexlify(fs.readFileSync(absolutePath).toString(), { allowMissingPrefix: true }); } } catch (err) { const msg = err instanceof Error ? err.message : "Unknown error"; diff --git a/system-contracts/scripts/compile-yul.ts b/system-contracts/scripts/compile-yul.ts index e8d91622b..e22f26b97 100644 --- a/system-contracts/scripts/compile-yul.ts +++ b/system-contracts/scripts/compile-yul.ts @@ -1,18 +1,11 @@ // hardhat import should be the first import in the file import type { CompilerPaths } from "./utils"; -import { - spawn, - compilerLocation, - prepareCompilerPaths, - getSolcLocation, - needsRecompilation, - setCompilationTime, -} from "./utils"; +import { spawn, compilerLocation, prepareCompilerPaths, needsRecompilation, setCompilationTime } from "./utils"; import * as fs from "fs"; import { Command } from "commander"; import * as _path from "path"; -const COMPILER_VERSION = "1.5.0"; +const COMPILER_VERSION = "1.5.6"; const IS_COMPILER_PRE_RELEASE = true; const CONTRACTS_DIR = "contracts-preprocessed"; const BOOTLOADER_DIR = "bootloader"; @@ -20,11 +13,9 @@ const TIMESTAMP_FILE_YUL = "last_compilation_yul.timestamp"; const TIMESTAMP_FILE_BOOTLOADER = "last_compilation_bootloader.timestamp"; export async function compileYul(paths: CompilerPaths, file: string) { - const solcCompilerPath = await getSolcLocation(); - const zksolcLocation = await compilerLocation(COMPILER_VERSION, IS_COMPILER_PRE_RELEASE); await spawn( - `${zksolcLocation} ${paths.absolutePathSources}/${file} --solc ${solcCompilerPath} --optimization 3 --system-mode --yul --bin --overwrite -o ${paths.absolutePathArtifacts}` + `${zksolcLocation} ${paths.absolutePathSources}/${file} --optimization 3 --enable-eravm-extensions --yul --bin --overwrite -o ${paths.absolutePathArtifacts}` ); } diff --git a/system-contracts/scripts/compile-zasm.ts b/system-contracts/scripts/compile-zasm.ts index 2e6e828a9..8ae15bf16 100644 --- a/system-contracts/scripts/compile-zasm.ts +++ b/system-contracts/scripts/compile-zasm.ts @@ -3,13 +3,13 @@ import type { CompilerPaths } from "./utils"; import { spawn, compilerLocation, prepareCompilerPaths } from "./utils"; import * as fs from "fs"; -const COMPILER_VERSION = "1.3.18"; +const COMPILER_VERSION = "1.5.6"; const IS_COMPILER_PRE_RELEASE = true; export async function compileZasm(paths: CompilerPaths, file: string) { const zksolcLocation = await compilerLocation(COMPILER_VERSION, IS_COMPILER_PRE_RELEASE); await spawn( - `${zksolcLocation} ${paths.absolutePathSources}/${file} --zkasm --bin --overwrite -o ${paths.absolutePathArtifacts}` + `${zksolcLocation} ${paths.absolutePathSources}/${file} --eravm-assembly --bin --overwrite -o ${paths.absolutePathArtifacts}` ); } diff --git a/system-contracts/scripts/deploy-preimages.ts b/system-contracts/scripts/deploy-preimages.ts index b13917a0e..719607916 100644 --- a/system-contracts/scripts/deploy-preimages.ts +++ b/system-contracts/scripts/deploy-preimages.ts @@ -13,7 +13,14 @@ import { Provider, Wallet } from "zksync-ethers"; import { hashBytecode } from "zksync-ethers/build/utils"; import { Language, SYSTEM_CONTRACTS } from "./constants"; import type { Dependency, DeployedDependency } from "./utils"; -import { checkMarkers, filterPublishedFactoryDeps, getBytecodes, publishFactoryDeps, readYulBytecode } from "./utils"; +import { + checkMarkers, + filterPublishedFactoryDeps, + getBytecodes, + publishFactoryDeps, + readBytecodeUtf8, + readYulBytecode, +} from "./utils"; const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, "etc/test_config/constant"); const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: "utf-8" })); @@ -239,7 +246,7 @@ class ZkSyncDeployer { } async processBootloader() { - const bootloaderCode = ethers.utils.hexlify(fs.readFileSync("./bootloader/build/artifacts/proved_batch.yul.zbin")); + const bootloaderCode = readBytecodeUtf8("./bootloader/build/artifacts/proved_batch.yul.zbin"); await this.publishBootloader(bootloaderCode); await this.checkShouldUpgradeBootloader(bootloaderCode); diff --git a/system-contracts/scripts/utils.ts b/system-contracts/scripts/utils.ts index 4c1060ee2..cfba8345a 100644 --- a/system-contracts/scripts/utils.ts +++ b/system-contracts/scripts/utils.ts @@ -34,14 +34,18 @@ export interface DeployedDependency { export function readYulBytecode(description: YulContractDescription) { const contractName = description.codeName; - const path = `contracts-preprocessed/${description.path}/artifacts/${contractName}.yul.zbin`; - return ethers.utils.hexlify(fs.readFileSync(path)); + const path = `contracts-preprocessed/${description.path}/artifacts/${contractName}.yul/${contractName}.yul.zbin`; + return readBytecodeUtf8(path); } export function readZasmBytecode(description: ZasmContractDescription) { const contractName = description.codeName; - const path = `contracts-preprocessed/${description.path}/artifacts/${contractName}.zasm.zbin`; - return ethers.utils.hexlify(fs.readFileSync(path)); + const path = `contracts-preprocessed/${description.path}/artifacts/${contractName}.zasm/${contractName}.zasm.zbin`; + return readBytecodeUtf8(path); +} + +export function readBytecodeUtf8(path: string) { + return ethers.utils.hexlify(fs.readFileSync(path).toString(), { allowMissingPrefix: true }); } // The struct used to represent the parameters of a forced deployment -- a deployment during upgrade diff --git a/yarn.lock b/yarn.lock index 66cd67b1a..4df7c8718 100644 --- a/yarn.lock +++ b/yarn.lock @@ -772,6 +772,23 @@ sinon-chai "^3.7.0" undici "^5.14.0" +"@matterlabs/hardhat-zksync-solc@^1.2.5": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-solc/-/hardhat-zksync-solc-1.2.5.tgz#fbeeabc3fea0dd232fa3c8cb31bd93c103eba11a" + integrity sha512-iZyznWl1Hoe/Z46hnUe1s2drBZBjJOS/eN+Ql2lIBX9B6NevBl9DYzkKzH5HEIMCLGnX9sWpRAJqUQJWy9UB6w== + dependencies: + "@nomiclabs/hardhat-docker" "^2.0.2" + chai "^4.3.4" + chalk "^4.1.2" + debug "^4.3.5" + dockerode "^4.0.2" + fs-extra "^11.2.0" + proper-lockfile "^4.1.2" + semver "^7.6.2" + sinon "^18.0.0" + sinon-chai "^3.7.0" + undici "^6.18.2" + "@matterlabs/hardhat-zksync-verify@0.6.1": version "0.6.1" resolved "https://registry.yarnpkg.com/@matterlabs/hardhat-zksync-verify/-/hardhat-zksync-verify-0.6.1.tgz#3fd83f4177ac0b138656ed93d4756ec27f1d329d" @@ -1181,7 +1198,7 @@ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.1" "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.1" -"@nomiclabs/hardhat-docker@^2.0.0": +"@nomiclabs/hardhat-docker@^2.0.0", "@nomiclabs/hardhat-docker@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-docker/-/hardhat-docker-2.0.2.tgz#ae964be17951275a55859ff7358e9e7c77448846" integrity sha512-XgGEpRT3wlA1VslyB57zyAHV+oll8KnV1TjwnxxC1tpAL04/lbdwpdO5KxInVN8irMSepqFpsiSkqlcnvbE7Ng== @@ -1413,20 +1430,27 @@ dependencies: type-detect "4.0.8" -"@sinonjs/commons@^3.0.0": +"@sinonjs/commons@^3.0.0", "@sinonjs/commons@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@^11.2.2": +"@sinonjs/fake-timers@11.2.2", "@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== dependencies: "@sinonjs/commons" "^3.0.0" +"@sinonjs/fake-timers@^13.0.1": + version "13.0.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-13.0.2.tgz#3ffe88abb062067a580fdfba706ad00435a0f2a6" + integrity sha512-4Bb+oqXZTSTZ1q27Izly9lv8B9dlV61CROxPiVtywwzv5SnytJqhvYe6FclHYuXml4cd1VHPo1zd5PmTeJozvA== + dependencies: + "@sinonjs/commons" "^3.0.1" + "@sinonjs/samsam@^8.0.0": version "8.0.0" resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.0.tgz#0d488c91efb3fa1442e26abea81759dfc8b5ac60" @@ -1441,6 +1465,11 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== +"@sinonjs/text-encoding@^0.7.3": + 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== + "@solidity-parser/parser@^0.14.0": version "0.14.5" resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" @@ -2549,6 +2578,19 @@ chai@^4.3.10, chai@^4.3.6, chai@^4.3.7: pathval "^1.1.1" type-detect "^4.0.8" +chai@^4.3.4: + version "4.5.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8" + integrity sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" + pathval "^1.1.1" + type-detect "^4.1.0" + chalk@4.1.2, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -2961,6 +3003,13 @@ debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.5: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" @@ -3041,7 +3090,7 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -diff@^5.1.0: +diff@^5.1.0, diff@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== @@ -4004,7 +4053,7 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^11.1.1: +fs-extra@^11.1.1, fs-extra@^11.2.0: version "11.2.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== @@ -5774,7 +5823,7 @@ 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.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -5815,6 +5864,17 @@ nise@^5.1.5: just-extend "^6.2.0" path-to-regexp "^6.2.1" +nise@^6.0.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/nise/-/nise-6.1.1.tgz#78ea93cc49be122e44cb7c8fdf597b0e8778b64a" + integrity sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g== + dependencies: + "@sinonjs/commons" "^3.0.1" + "@sinonjs/fake-timers" "^13.0.1" + "@sinonjs/text-encoding" "^0.7.3" + just-extend "^6.2.0" + path-to-regexp "^8.1.0" + 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" @@ -6102,6 +6162,11 @@ path-to-regexp@^6.2.1: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz#324377a83e5049cbecadc5554d6a63a9a4866b36" integrity sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw== +path-to-regexp@^8.1.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.2.0.tgz#73990cc29e57a3ff2a0d914095156df5db79e8b4" + integrity sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -6696,6 +6761,11 @@ semver@^7.3.7: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.1.tgz#60bfe090bf907a25aa8119a72b9f90ef7ca281b2" integrity sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA== +semver@^7.6.2: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" @@ -6809,6 +6879,18 @@ sinon@^17.0.1: nise "^5.1.5" supports-color "^7.2.0" +sinon@^18.0.0: + version "18.0.1" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-18.0.1.tgz#464334cdfea2cddc5eda9a4ea7e2e3f0c7a91c5e" + integrity sha512-a2N2TDY1uGviajJ6r4D1CyRAkzE9NNVlYOV1wX5xQDuAk0ONgzgRl0EjCQuRCPxOwp13ghsMwt9Gdldujs39qw== + dependencies: + "@sinonjs/commons" "^3.0.1" + "@sinonjs/fake-timers" "11.2.2" + "@sinonjs/samsam" "^8.0.0" + diff "^5.2.0" + nise "^6.0.0" + supports-color "^7" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -7159,7 +7241,7 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0, supports-color@^7.2.0: +supports-color@^7, 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== @@ -7485,6 +7567,11 @@ type-detect@4.0.8, type-detect@^4.0.0, type-detect@^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.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" @@ -7635,6 +7722,11 @@ 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" @@ -7931,10 +8023,3 @@ zksync-ethers@^5.9.0: integrity sha512-Y2Mx6ovvxO6UdC2dePLguVzvNToOY8iLWeq5ne+jgGSJxAi/f4He/NF6FNsf6x1aWX0o8dy4Df8RcOQXAkj5qw== dependencies: ethers "~5.7.0" - -zksync-web3@^0.15.4: - version "0.15.5" - resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.15.5.tgz#aabe379464963ab573e15948660a709f409b5316" - integrity sha512-97gB7OKJL4spegl8fGO54g6cvTd/75G6yFWZWEa2J09zhjTrfqabbwE/GwiUJkFQ5BbzoH4JaTlVz1hoYZI+DQ== - dependencies: - ethers "~5.7.0" From 418b4a9f1ea37ecef635b5e3b92d1e953e8778e0 Mon Sep 17 00:00:00 2001 From: Vladimir Radosavljevic <129192835+vladimirradosavljevic@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:31:38 +0200 Subject: [PATCH 074/183] feat(EVM-emulator): add support for propagating LLVM options (#858) Signed-off-by: Vladimir Radosavljevic Co-authored-by: Vladislav Volosnikov --- .../contracts/EvmEmulator.yul.llvm.options | 1 + system-contracts/scripts/compile-yul.ts | 16 +++++++++++++++- .../scripts/preprocess-system-contracts.ts | 6 +++++- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 system-contracts/contracts/EvmEmulator.yul.llvm.options diff --git a/system-contracts/contracts/EvmEmulator.yul.llvm.options b/system-contracts/contracts/EvmEmulator.yul.llvm.options new file mode 100644 index 000000000..98f38d107 --- /dev/null +++ b/system-contracts/contracts/EvmEmulator.yul.llvm.options @@ -0,0 +1 @@ +'-eravm-jump-table-density-threshold=10 -tail-dup-size=4 -eravm-enable-split-loop-phi-live-ranges -tail-merge-only-bbs-without-succ' \ No newline at end of file diff --git a/system-contracts/scripts/compile-yul.ts b/system-contracts/scripts/compile-yul.ts index e22f26b97..29ad84142 100644 --- a/system-contracts/scripts/compile-yul.ts +++ b/system-contracts/scripts/compile-yul.ts @@ -1,4 +1,5 @@ // hardhat import should be the first import in the file +import { existsSync } from "fs"; import type { CompilerPaths } from "./utils"; import { spawn, compilerLocation, prepareCompilerPaths, needsRecompilation, setCompilationTime } from "./utils"; import * as fs from "fs"; @@ -11,11 +12,24 @@ const CONTRACTS_DIR = "contracts-preprocessed"; const BOOTLOADER_DIR = "bootloader"; const TIMESTAMP_FILE_YUL = "last_compilation_yul.timestamp"; const TIMESTAMP_FILE_BOOTLOADER = "last_compilation_bootloader.timestamp"; +const LLVM_OPTIONS_FILE_EXTENSION = ".llvm.options"; export async function compileYul(paths: CompilerPaths, file: string) { const zksolcLocation = await compilerLocation(COMPILER_VERSION, IS_COMPILER_PRE_RELEASE); + + const filePath = `${paths.absolutePathSources}/${file}`; + const llvmOptionsFilePath = `${filePath}${LLVM_OPTIONS_FILE_EXTENSION}`; + let llvmOptions = ""; + if (existsSync(llvmOptionsFilePath)) { + const llvmOptionsFileContent = (await fs.promises.readFile(llvmOptionsFilePath)).toString(); + if (!llvmOptionsFileContent.startsWith("'") || !llvmOptionsFileContent.endsWith("'")) { + throw new Error(`Content in ${llvmOptionsFilePath} must start and end with a single quote.`); + } + llvmOptions = `--llvm-options=${llvmOptionsFileContent}`; + } + await spawn( - `${zksolcLocation} ${paths.absolutePathSources}/${file} --optimization 3 --enable-eravm-extensions --yul --bin --overwrite -o ${paths.absolutePathArtifacts}` + `${zksolcLocation} ${paths.absolutePathSources}/${file} --optimization 3 ${llvmOptions} --enable-eravm-extensions --yul --bin --overwrite -o ${paths.absolutePathArtifacts}` ); } diff --git a/system-contracts/scripts/preprocess-system-contracts.ts b/system-contracts/scripts/preprocess-system-contracts.ts index 0b3690a9e..4237ed12e 100644 --- a/system-contracts/scripts/preprocess-system-contracts.ts +++ b/system-contracts/scripts/preprocess-system-contracts.ts @@ -1,4 +1,4 @@ -import { existsSync, mkdirSync, writeFileSync } from "fs"; +import { copyFileSync, existsSync, mkdirSync, writeFileSync } from "fs"; import path from "path"; import { renderFile } from "template-file"; import { glob } from "fast-glob"; @@ -8,6 +8,7 @@ import { needsRecompilation, deleteDir, setCompilationTime, isFolderEmpty } from const CONTRACTS_DIR = "contracts"; const OUTPUT_DIR = "contracts-preprocessed"; const TIMESTAMP_FILE = "last_compilation_preprocessing.timestamp"; // File to store the last compilation time +const LLVM_OPTIONS_FILE_EXTENSION = ".llvm.options"; const params = { SYSTEM_CONTRACTS_OFFSET: "0x8000", @@ -44,6 +45,9 @@ async function preprocess(testMode: boolean) { mkdirSync(directory, { recursive: true }); } writeFileSync(fileName, preprocessed); + if (existsSync(contract + LLVM_OPTIONS_FILE_EXTENSION)) { + copyFileSync(contract + LLVM_OPTIONS_FILE_EXTENSION, fileName + LLVM_OPTIONS_FILE_EXTENSION); + } } console.log("System Contracts preprocessing done!"); From f33c6537885cb5edbcbb6afb324345614d9ae429 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 18 Oct 2024 11:28:14 +0200 Subject: [PATCH 075/183] feat(EVM-emulator): Optimize deployment of EVM contracts (#827) --- system-contracts/SystemContractsHashes.json | 40 ++++----- .../contracts/ContractDeployer.sol | 86 +++++++------------ system-contracts/contracts/EvmEmulator.yul | 36 +------- .../contracts/KnownCodesStorage.sol | 20 +++-- .../interfaces/IContractDeployer.sol | 2 - .../interfaces/IKnownCodesStorage.sol | 2 +- .../evm-emulator/EvmEmulator.template.yul | 36 +------- system-contracts/hardhat.config.ts | 1 - 8 files changed, 70 insertions(+), 153 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index c4a4cb894..9bd8c2740 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": "0x01000077b3a2e71f210798dbc12daf83c3db44a302475ecf0ac867dc2649aa68", + "bytecodeHash": "0x01000077ff6c1c34569110a8608219b3ecb5c73ec5822cfe10badca14c66cba7", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f183c7aecce751c6e94e7aac21d5c1f1cc732e04aa683c9ed1f3ba52a4", + "bytecodeHash": "0x010006f183a232235d55478e95ea8c581aa1d955a00781107a4ad45f9844ec8d", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004703396a30dda1dc9508debedcf1c67871e3a03a84ec6829a6bc13dc30", + "bytecodeHash": "0x01000047933a41a300a297c271e22757d46313de12d51801649ca957897ce976", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013fc867576077f4db1a5132bd19a62150ae5ae90e39a39c5e15fee1f87c", + "bytecodeHash": "0x0100013ff8b20b52b048cb4938d73f5d2a338c00ff37668083bbc94992bca93e", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x0100062b38145654a769280b0c6f989d3ca348f117f5476d6f9d9417926be472", - "sourceCodeHash": "0xa1adab82a0cc20a33f53059520bf256e3a01e704f49c7dab528a26c21f8fcb14" + "bytecodeHash": "0x010005c1c55f3db9307fb5e4a7931c55c533cc603779a55708b55ecb1ded56cd", + "sourceCodeHash": "0x8fecd5c1284ade078f91ba270a2c0a96e91475861cceff7304d17469fd8e0ef2" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003ff6c98eb1f7ed6920cc59c447f2fd5e5d96a94ab7a10354dcb315e3c4", + "bytecodeHash": "0x0100003f9842af3a02d815564d69c63be81267824086e24e30e3f3efb186e4bc", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x010005037272b2cbe84aa944a3c8891dd761a28c9c5bef947894b731d1b814c3", + "bytecodeHash": "0x0100050374c233622ec7a2fed14f1c2d2a6c809157ff99c60c5a8658bf9f53b4", "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { @@ -59,63 +59,63 @@ "contractName": "EvmGasManager", "bytecodePath": "artifacts-zk/contracts-preprocessed/EvmGasManager.sol/EvmGasManager.json", "sourceCodePath": "contracts-preprocessed/EvmGasManager.sol", - "bytecodeHash": "0x0100008148ea7fa07f7ba421637904013bb2421ff55367e8c440eed44df928ae", + "bytecodeHash": "0x01000081e078c7fad2fa012c39a89d78e6afd637146dabe3baaa984de203b435", "sourceCodeHash": "0x56e3898a4cd8af13abf91fa2296900e0b5f409ee3ca4296a0f08affbe31da244" }, { "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x010000330a7a1d11b522a1ad580e4b89b553cbc7f7fb50cdd28b92eccdd2dbff", + "bytecodeHash": "0x01000033775c3ac3ee876a3e9f66ee3a75075f691d1a67212a6348e2884751e9", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000bd9bfab7f24e22c2aae3d39f1cdd1c86c152102e378eda2e84ea9964d1", - "sourceCodeHash": "0xe07e6543ac09b86042eff5f9067df6db10a4fc039ecb56098a882ee1019c3031" + "bytecodeHash": "0x010000c15386a7ee2aeb3d87ed0c69af5f75d66d64cb266a90f573f517354bcf", + "sourceCodeHash": "0xd19ebf4cf153de38a62229e4663b73fbeaaa7195527eb9ebb07214ce4c6751ea" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010002654ccbe8aebd01bcc004f4106d086c578421a2dafb87704248470e5f53", + "bytecodeHash": "0x010002653d669a6a17c5fc7a96526ab131559478d42ec7bea6fd7df9bdf97d26", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f359f25508b815beaa278ff6743c007c48972aac746fe7af827867cf50", + "bytecodeHash": "0x010000f3f9dcc5a3e4a85d500de0205772071ab1642d363a44a7ac08f2c1bcc3", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x010000594f5e8c6b056fbaad49b2ae4d23c034542ab143831752afd14095864c", + "bytecodeHash": "0x01000059826ee09524d28d554bad42142df946ae94bb0d2e5e844326e8cdcbd5", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cf90f3f2f80ae737aea3509d2be433139e76e37315b459fcd7946150d1", + "bytecodeHash": "0x010000cf4926b96899ec451befa596c0360adb11fbe19d404bda49c16a9f1fa6", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041433d7470dedc89405ccb43b5b7e99ee1b874a5d1b55c02d40c159658", + "bytecodeHash": "0x01000041d0b27dd245eb09e5a05b6631865366a4f1346ffd9eabaad9af7310e6", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a544226c8f7069254a18c6bd56efa0bbf3438a582c4abc323b9d789c32", + "bytecodeHash": "0x010001a547c523bd47d62e95222e6ebf4de576905bbd22a1d331b0f83f028fff", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { @@ -129,8 +129,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000bdff42de9af35c542b2391edb91529ebb0f90eb9adf80707c295c8bbd66", - "sourceCodeHash": "0x09dc71f1238d306f0fdbab79197a3c4d299eeaf287c62ecd0da1fb8b85529bcc" + "bytecodeHash": "0x01000df51fcd725d40dad02aa613eff2afaba03bbbeded4289451c271fc35a04", + "sourceCodeHash": "0xf2dd3475f96b8ebb047e135dc63fc40f929f626895cb713ec98d797913adcd43" }, { "contractName": "CodeOracle", diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 15656eda8..ba0644b6d 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -28,38 +28,8 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { /// @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 - } - uint256 private constant EVM_HASHES_PREFIX = 1 << 254; - - uint256 public constructorReturnGas; - - 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])); - bytes memory trueBytecode = paddedNewDeployedCode[32:32 + bytecodeLen]; - - _setEvmCodeHash(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); - } + uint256 private constant CONSTRUCTOR_RETURN_GAS_SLOT = 1; modifier onlySelf() { if (msg.sender != address(this)) { @@ -72,6 +42,12 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _hash = _getEvmCodeHash(_address); } + function constructorReturnGas() external view returns (uint256 returnGas) { + assembly { + returnGas := tload(CONSTRUCTOR_RETURN_GAS_SLOT) + } + } + /// @notice Returns information about a certain account. function getAccountInfo(address _address) external view returns (AccountInfo memory info) { return accountInfo[_address]; @@ -396,24 +372,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { }); } - function convertToConstructorEVMInput(bytes calldata _input) internal pure returns (bytes memory) { - // 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); - - 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. @@ -510,8 +468,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { // 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) { @@ -532,7 +488,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { SystemContractHelper.setValueForNextFarCall(uint128(value)); } - bool success = EfficientCall.rawMimicCall({ + bytes memory paddedBytecode = EfficientCall.mimicCall({ _gas: uint32(gasleft()), _address: _newAddress, _data: _input, @@ -541,13 +497,29 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _isSystem: false }); - if (!success) { - EfficientCall.propagateRevert(); + uint256 constructorReturnGas; + assembly { + let dataLen := mload(paddedBytecode) + constructorReturnGas := mload(add(paddedBytecode, dataLen)) + mstore(paddedBytecode, sub(dataLen, 0x20)) + } + + bytes32 versionedCodeHash = KNOWN_CODE_STORAGE_CONTRACT.publishEVMBytecode(paddedBytecode); + ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.storeAccountConstructedCodeHash(_newAddress, versionedCodeHash); + + bytes32 evmBytecodeHash; + assembly { + let bytecodeLen := mload(add(paddedBytecode, 0x20)) + evmBytecodeHash := keccak256(add(paddedBytecode, 0x40), bytecodeLen) + } + + _setEvmCodeHash(_newAddress, evmBytecodeHash); + + assembly { + tstore(CONSTRUCTOR_RETURN_GAS_SLOT, constructorReturnGas) } - bytes32 codeHash = _getEvmCodeHash(_newAddress); - require(codeHash != 0x0, "The code hash must be set after the constructor call"); - emit ContractDeployed(_sender, codeHash, _newAddress); + emit ContractDeployed(_sender, evmBytecodeHash, _newAddress); } function _setEvmCodeHash(address _address, bytes32 _hash) internal { diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index b13e6447c..b9325a40b 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -15,38 +15,6 @@ object "EvmEmulator" { 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) @@ -2910,7 +2878,9 @@ object "EvmEmulator" { offset, len := padBytecode(offset, len) - setDeployedCode(gasToReturn, offset, len) + mstore(add(offset, len), gasToReturn) + + verbatim_2i_0o("return_deployed", offset, add(len, 32)) } object "EvmEmulator_deployed" { code { diff --git a/system-contracts/contracts/KnownCodesStorage.sol b/system-contracts/contracts/KnownCodesStorage.sol index 378eeecd2..d0d8bcae0 100644 --- a/system-contracts/contracts/KnownCodesStorage.sol +++ b/system-contracts/contracts/KnownCodesStorage.sol @@ -85,23 +85,31 @@ contract KnownCodesStorage is IKnownCodesStorage, SystemContractBase { } } - function publishEVMBytecode(bytes calldata bytecode) external onlyCallFrom(address(DEPLOYER_SYSTEM_CONTRACT)) { + function publishEVMBytecode( + bytes calldata paddedBytecode + ) external payable onlyCallFrom(address(DEPLOYER_SYSTEM_CONTRACT)) returns (bytes32) { /* TODO: ensure that it is properly padded, etc. To preserve EVM compatibility, we can not emit any events here. */ - bytes32 hash = Utils.hashEVMBytecode(bytecode); + // ToDO: use efficient call + bytes32 vesionedBytecodeHash = Utils.hashEVMBytecode(paddedBytecode); - if (getMarker(hash) == 0) { + if (getMarker(vesionedBytecodeHash) == 0) { // ToDO: use efficient call - L1_MESSENGER_CONTRACT.sendToL1(bytecode); + L1_MESSENGER_CONTRACT.sendToL1(paddedBytecode); assembly { - sstore(hash, 1) + sstore(vesionedBytecodeHash, 1) } + + emit MarkedAsKnown(vesionedBytecodeHash, true); } - emit MarkedAsKnown(hash, getMarker(hash) == 0); + assembly { + mstore(0x0, vesionedBytecodeHash) + return(0x0, 0x20) + } } } diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index f42403d3a..9046e7921 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -95,7 +95,5 @@ interface IContractDeployer { 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/IKnownCodesStorage.sol b/system-contracts/contracts/interfaces/IKnownCodesStorage.sol index 630b41f25..984f203aa 100644 --- a/system-contracts/contracts/interfaces/IKnownCodesStorage.sol +++ b/system-contracts/contracts/interfaces/IKnownCodesStorage.sol @@ -17,5 +17,5 @@ interface IKnownCodesStorage { function getMarker(bytes32 _hash) external view returns (uint256); - function publishEVMBytecode(bytes calldata bytecode) external; + function publishEVMBytecode(bytes calldata bytecode) external payable returns (bytes32); } diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index 2ac84f0c0..ffbb04cae 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -15,38 +15,6 @@ object "EvmEmulator" { 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) @@ -120,7 +88,9 @@ object "EvmEmulator" { offset, len := padBytecode(offset, len) - setDeployedCode(gasToReturn, offset, len) + mstore(add(offset, len), gasToReturn) + + verbatim_2i_0o("return_deployed", offset, add(len, 32)) } object "EvmEmulator_deployed" { code { diff --git a/system-contracts/hardhat.config.ts b/system-contracts/hardhat.config.ts index 5a6ab2986..3b03302c8 100644 --- a/system-contracts/hardhat.config.ts +++ b/system-contracts/hardhat.config.ts @@ -5,7 +5,6 @@ import "@matterlabs/hardhat-zksync-verify"; import "@nomiclabs/hardhat-ethers"; import "hardhat-typechain"; -// This version of system contracts requires a pre release of the compiler const COMPILER_VERSION = "v1.5.6"; const PRE_RELEASE_VERSION = "1.5.6"; function getZksolcUrl(): string { From a3fc4b02c19bd5f2c2c3c004342f094e2c6a83b9 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 18 Oct 2024 13:03:45 +0200 Subject: [PATCH 076/183] feat(EVM): Implement EvmGasManager in yul (#943) --- system-contracts/SystemContractsHashes.json | 48 ++--- system-contracts/contracts/Constants.sol | 3 +- system-contracts/contracts/EvmEmulator.yul | 140 ++++++------ system-contracts/contracts/EvmGasManager.sol | 177 --------------- system-contracts/contracts/EvmGasManager.yul | 203 ++++++++++++++++++ .../contracts/interfaces/IEvmGasManager.sol | 14 -- .../EvmEmulatorFunctions.template.yul | 70 +++--- 7 files changed, 345 insertions(+), 310 deletions(-) delete mode 100644 system-contracts/contracts/EvmGasManager.sol create mode 100644 system-contracts/contracts/EvmGasManager.yul delete mode 100644 system-contracts/contracts/interfaces/IEvmGasManager.sol diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 9bd8c2740..0615c2792 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": "0x01000077ff6c1c34569110a8608219b3ecb5c73ec5822cfe10badca14c66cba7", + "bytecodeHash": "0x0100007723fbe7d5aa0b9eafd79b3e776b290726254b7bfda267c8fe63480703", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f183a232235d55478e95ea8c581aa1d955a00781107a4ad45f9844ec8d", + "bytecodeHash": "0x010006f1e17b338570641527be4a4548b80b8c6dff188959c253842b115be17b", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x01000047933a41a300a297c271e22757d46313de12d51801649ca957897ce976", + "bytecodeHash": "0x01000047d537ae233868d05129ce4c590032c489b4cf07c96e5b9d9a0f6507c9", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013ff8b20b52b048cb4938d73f5d2a338c00ff37668083bbc94992bca93e", + "bytecodeHash": "0x0100013f6b31caf9414e0e55165a527d2ec0ae05dbd9ce6cc1515609e971f31f", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010005c1c55f3db9307fb5e4a7931c55c533cc603779a55708b55ecb1ded56cd", + "bytecodeHash": "0x010005c167a5031dcd06144c2b9ea1625927317e754847f977f5cdc120c3b11a", "sourceCodeHash": "0x8fecd5c1284ade078f91ba270a2c0a96e91475861cceff7304d17469fd8e0ef2" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003f9842af3a02d815564d69c63be81267824086e24e30e3f3efb186e4bc", + "bytecodeHash": "0x0100003f7cdb25550a4f1aeb5273582f52ea4009c732891d0dfe77f0cf1ba0d8", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100050374c233622ec7a2fed14f1c2d2a6c809157ff99c60c5a8658bf9f53b4", + "bytecodeHash": "0x01000503285b02130b8fc5d7bd876650285a4224988605ee8171cf48f2856f1a", "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { @@ -55,67 +55,60 @@ "bytecodeHash": "0x01000007947dfd1aab45b52e5998b442bfbd4d565af494fb8082a810c6ed0b50", "sourceCodeHash": "0xcac36c5afafbcff83601f4fbfdff660aa66d8c80ed97b9322d3011c1926b554d" }, - { - "contractName": "EvmGasManager", - "bytecodePath": "artifacts-zk/contracts-preprocessed/EvmGasManager.sol/EvmGasManager.json", - "sourceCodePath": "contracts-preprocessed/EvmGasManager.sol", - "bytecodeHash": "0x01000081e078c7fad2fa012c39a89d78e6afd637146dabe3baaa984de203b435", - "sourceCodeHash": "0x56e3898a4cd8af13abf91fa2296900e0b5f409ee3ca4296a0f08affbe31da244" - }, { "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033775c3ac3ee876a3e9f66ee3a75075f691d1a67212a6348e2884751e9", + "bytecodeHash": "0x01000033e5376655c78111a162af76c4123514d6a1c674c546c5b8743932a66b", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000c15386a7ee2aeb3d87ed0c69af5f75d66d64cb266a90f573f517354bcf", + "bytecodeHash": "0x010000c1242abf7683aa2be6c873109d418e5e1fd76d8a54a27d30248fbcdb4f", "sourceCodeHash": "0xd19ebf4cf153de38a62229e4663b73fbeaaa7195527eb9ebb07214ce4c6751ea" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010002653d669a6a17c5fc7a96526ab131559478d42ec7bea6fd7df9bdf97d26", + "bytecodeHash": "0x010002655f6300e6727889907b9bca66a8860c5c2856efd6255dfce087cce9f7", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f3f9dcc5a3e4a85d500de0205772071ab1642d363a44a7ac08f2c1bcc3", + "bytecodeHash": "0x010000f3ce3bf50b3f959d587f3cc85459bea4b72de6f9bd74ec73f4b71f1d30", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x01000059826ee09524d28d554bad42142df946ae94bb0d2e5e844326e8cdcbd5", + "bytecodeHash": "0x010000593cbabdacfca62483f479a180f4ea05e228897f1d242e278beda54d16", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cf4926b96899ec451befa596c0360adb11fbe19d404bda49c16a9f1fa6", + "bytecodeHash": "0x010000cf6010047bbbb07094e62a6e5d3118b43ffe774b3ab280d8b1e0459082", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041d0b27dd245eb09e5a05b6631865366a4f1346ffd9eabaad9af7310e6", + "bytecodeHash": "0x010000413ab00a975878979e83557ce0d8c96d896d69df966bba03d74b60efa5", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a547c523bd47d62e95222e6ebf4de576905bbd22a1d331b0f83f028fff", + "bytecodeHash": "0x010001a509d4a68571775f2c1a7fbe82842da52c6c8794e10af47723f6b0964c", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { @@ -129,8 +122,15 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000df51fcd725d40dad02aa613eff2afaba03bbbeded4289451c271fc35a04", - "sourceCodeHash": "0xf2dd3475f96b8ebb047e135dc63fc40f929f626895cb713ec98d797913adcd43" + "bytecodeHash": "0x01000dcdf3a70d93ce630d6607b87e6ca013819bb2b67cfd2d544c31c21dcce7", + "sourceCodeHash": "0x6b27cc953993aef0a2b009b5bcd67b9a6f738fcfa927ff40706e7ef9d66126c0" + }, + { + "contractName": "EvmGasManager", + "bytecodePath": "contracts-preprocessed/artifacts/EvmGasManager.yul/EvmGasManager.yul.zbin", + "sourceCodePath": "contracts-preprocessed/EvmGasManager.yul", + "bytecodeHash": "0x0100005577ee81de6b5334d9f91ea8d9a91f02e3afa057bb0455f2e2d8aac636", + "sourceCodeHash": "0xd27ca9819fad1f1dc3fbc7f2c90f5ba2a9907413036fc78efbcee33649c975cb" }, { "contractName": "CodeOracle", diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index dab28bfdc..20858729a 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -14,7 +14,6 @@ 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 {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 +84,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)); -IEvmGasManager constant EVM_GAS_MANAGER = IEvmGasManager(address(SYSTEM_CONTRACTS_OFFSET + 0x13)); +address constant EVM_GAS_MANAGER = address(SYSTEM_CONTRACTS_OFFSET + 0x13); IPubdataChunkPublisher constant PUBDATA_CHUNK_PUBLISHER = IPubdataChunkPublisher( address(SYSTEM_CONTRACTS_OFFSET + 0x11) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index b9325a40b..95e5f5361 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -337,13 +337,14 @@ object "EvmEmulator" { function consumeEvmFrame() -> passGas, isStatic, callerEVM { // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) - mstore(0, 0x04C14E9E00000000000000000000000000000000000000000000000000000000) + // non-standard selector 0x04 + mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) let farCallAbi := getFarCallABI( 0, 0, 0, - 4, + 1, gas(), // Only rollup is supported for now 0, @@ -359,14 +360,14 @@ object "EvmEmulator" { revert(0, 0) } - returndatacopy(0,0,64) + let _returndatasize := returndatasize() + if _returndatasize { + callerEVM := true - let auxData := mload(32) - callerEVM := gt(auxData, 1) - - if callerEVM { - isStatic := and(auxData, 1) + returndatacopy(0, 0, 32) passGas := mload(0) + + isStatic := gt(_returndatasize, 32) } } @@ -572,29 +573,33 @@ object "EvmEmulator" { } function isSlotWarm(key) -> isWarm { - mstore(0, 0x482D2E7400000000000000000000000000000000000000000000000000000000) - mstore(4, key) + // non-standard selector 0x01 + mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } - isWarm := mload(0) + if returndatasize() { + isWarm := true + } } function warmSlot(key,currentValue) -> isWarm, originalValue { - mstore(0, 0xBDF7816000000000000000000000000000000000000000000000000000000000) - mstore(4, key) - mstore(36,currentValue) + // non-standard selector 0x02 + mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) + mstore(33,currentValue) let farCallAbi := getFarCallABI( 0, 0, 0, - 68, + 65, gas(), // Only rollup is supported for now 0, @@ -610,10 +615,11 @@ object "EvmEmulator" { revert(0, 0) } - returndatacopy(0, 0, 64) - - isWarm := mload(0) - originalValue := mload(32) + if returndatasize() { + isWarm := true + returndatacopy(0, 0, 32) + originalValue := mload(0) + } } function getFarCallABI( @@ -654,14 +660,16 @@ object "EvmEmulator" { } function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { - mstore(0, 0x8DB2BA7800000000000000000000000000000000000000000000000000000000) - mstore(4, addr) + // function warmAccount(address account) + // non-standard selector 0x00 + // addr is packed in the same word with selector + mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) let farCallAbi := getFarCallABI( 0, 0, 0, - 36, + 32, gas(), // Only rollup is supported for now 0, @@ -677,8 +685,9 @@ object "EvmEmulator" { revert(0, 0) } - returndatacopy(0, 0, 32) - isWarm := mload(0) + if returndatasize() { + isWarm := true + } } function getRawNonce(addr) -> nonce { @@ -715,17 +724,16 @@ object "EvmEmulator" { } function _pushEVMFrame(_passGas, _isStatic) { - // function pushEVMFrame(uint256 _passGas, bool _isStatic) external - - mstore(0, 0xEAD7715600000000000000000000000000000000000000000000000000000000) - mstore(4, _passGas) - mstore(36, _isStatic) + // function pushEVMFrame + // non-standard selector 0x03 + mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) + mstore(32, _passGas) let farCallAbi := getFarCallABI( 0, 0, 0, - 68, + 64, gas(), // Only rollup is supported for now 0, @@ -3173,13 +3181,14 @@ object "EvmEmulator" { function consumeEvmFrame() -> passGas, isStatic, callerEVM { // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) - mstore(0, 0x04C14E9E00000000000000000000000000000000000000000000000000000000) + // non-standard selector 0x04 + mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) let farCallAbi := getFarCallABI( 0, 0, 0, - 4, + 1, gas(), // Only rollup is supported for now 0, @@ -3195,14 +3204,14 @@ object "EvmEmulator" { revert(0, 0) } - returndatacopy(0,0,64) + let _returndatasize := returndatasize() + if _returndatasize { + callerEVM := true - let auxData := mload(32) - callerEVM := gt(auxData, 1) - - if callerEVM { - isStatic := and(auxData, 1) + returndatacopy(0, 0, 32) passGas := mload(0) + + isStatic := gt(_returndatasize, 32) } } @@ -3408,29 +3417,33 @@ object "EvmEmulator" { } function isSlotWarm(key) -> isWarm { - mstore(0, 0x482D2E7400000000000000000000000000000000000000000000000000000000) - mstore(4, key) + // non-standard selector 0x01 + mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } - isWarm := mload(0) + if returndatasize() { + isWarm := true + } } function warmSlot(key,currentValue) -> isWarm, originalValue { - mstore(0, 0xBDF7816000000000000000000000000000000000000000000000000000000000) - mstore(4, key) - mstore(36,currentValue) + // non-standard selector 0x02 + mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) + mstore(33,currentValue) let farCallAbi := getFarCallABI( 0, 0, 0, - 68, + 65, gas(), // Only rollup is supported for now 0, @@ -3446,10 +3459,11 @@ object "EvmEmulator" { revert(0, 0) } - returndatacopy(0, 0, 64) - - isWarm := mload(0) - originalValue := mload(32) + if returndatasize() { + isWarm := true + returndatacopy(0, 0, 32) + originalValue := mload(0) + } } function getFarCallABI( @@ -3490,14 +3504,16 @@ object "EvmEmulator" { } function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { - mstore(0, 0x8DB2BA7800000000000000000000000000000000000000000000000000000000) - mstore(4, addr) + // function warmAccount(address account) + // non-standard selector 0x00 + // addr is packed in the same word with selector + mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) let farCallAbi := getFarCallABI( 0, 0, 0, - 36, + 32, gas(), // Only rollup is supported for now 0, @@ -3513,8 +3529,9 @@ object "EvmEmulator" { revert(0, 0) } - returndatacopy(0, 0, 32) - isWarm := mload(0) + if returndatasize() { + isWarm := true + } } function getRawNonce(addr) -> nonce { @@ -3551,17 +3568,16 @@ object "EvmEmulator" { } function _pushEVMFrame(_passGas, _isStatic) { - // function pushEVMFrame(uint256 _passGas, bool _isStatic) external - - mstore(0, 0xEAD7715600000000000000000000000000000000000000000000000000000000) - mstore(4, _passGas) - mstore(36, _isStatic) + // function pushEVMFrame + // non-standard selector 0x03 + mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) + mstore(32, _passGas) let farCallAbi := getFarCallABI( 0, 0, 0, - 68, + 64, gas(), // Only rollup is supported for now 0, diff --git a/system-contracts/contracts/EvmGasManager.sol b/system-contracts/contracts/EvmGasManager.sol deleted file mode 100644 index dab8c4834..000000000 --- a/system-contracts/contracts/EvmGasManager.sol +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: MIT - -// solhint-disable reason-string, gas-custom-errors - -pragma solidity ^0.8.0; - -import {Utils} from "./libraries/Utils.sol"; - -import {ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "./Constants.sol"; -import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; -import {SystemCallFlagRequired, CallerMustBeEvmContract} from "./SystemContractErrors.sol"; - -// We consider all the contracts (including system ones) as warm. -uint160 constant PRECOMPILES_END = 0xffff; - -// 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_GAS_SLOT = 4; -uint256 constant EVM_AUX_DATA_SLOT = 5; -uint256 constant EVM_ACTIVE_FRAME_FLAG = 1 << 1; - -contract EvmGasManager { - modifier onlySystemEvm() { - if (!SystemContractHelper.isSystemCall()) { - revert SystemCallFlagRequired(); - } - - // cache use is safe since we do not support SELFDESTRUCT - uint256 _sender = uint256(uint160(msg.sender)); - uint256 transient_slot = IS_ACCOUNT_EVM_PREFIX | _sender; - bool isEVM; - assembly { - isEVM := tload(transient_slot) - } - - if (!isEVM) { - address to = address(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT); - bytes32 rawCodeHash; - assembly { - // function getRawCodeHash(address _address) public view returns (bytes32 codeHash) - mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) - mstore(4, _sender) - - let success := staticcall(gas(), to, 0, 36, 0, 32) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - rawCodeHash := mload(0) - } - - isEVM = Utils.isCodeHashEVM(rawCodeHash); - if (isEVM) { - if (!Utils.isContractConstructing(rawCodeHash)) { - assembly { - tstore(transient_slot, isEVM) - } - } - } else { - revert CallerMustBeEvmContract(); - } - } - _; - } - - /* - 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; - uint256 transient_slot = IS_ACCOUNT_WARM_PREFIX | uint256(uint160(account)); - - assembly { - wasWarm := tload(transient_slot) - - if iszero(wasWarm) { - tstore(transient_slot, 1) - } - - mstore(0x0, wasWarm) - return(0x0, 0x20) - } - } - - 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) - isWarm := tload(transient_slot) - - mstore(0x0, isWarm) - return(0x0, 0x20) - } - } - - 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) - - isWarm := tload(transient_slot) - - switch isWarm - case 0 { - originalValue := _currentValue - tstore(transient_slot, 1) - tstore(add(transient_slot, 1), originalValue) - } - default { - originalValue := tload(add(transient_slot, 1)) - } - - mstore(0x0, isWarm) - mstore(0x20, originalValue) - return(0x0, 0x40) - } - } - - /* - 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 and determine if a call is static, frame is marked as used - */ - - function pushEVMFrame(uint256 passGas, bool isStatic) external payable onlySystemEvm { - assembly { - tstore(EVM_GAS_SLOT, passGas) - tstore(EVM_AUX_DATA_SLOT, or(isStatic, EVM_ACTIVE_FRAME_FLAG)) - } - } - - function consumeEvmFrame() external payable onlySystemEvm returns (uint256 passGas, uint256 auxDataRes) { - bool isFrameActive; - bytes32 auxData; - assembly { - auxData := tload(EVM_AUX_DATA_SLOT) - isFrameActive := and(auxData, EVM_ACTIVE_FRAME_FLAG) - } - - if (isFrameActive) { - assembly { - passGas := tload(EVM_GAS_SLOT) - auxDataRes := auxData - - tstore(EVM_AUX_DATA_SLOT, 0) // mark as consumed - } - } else { - // add sender to the warm accounts - uint256 is_sender_warm_tslot = IS_ACCOUNT_WARM_PREFIX | uint256(uint160(msg.sender)); - assembly { - tstore(is_sender_warm_tslot, 1) - } - } - - assembly { - mstore(0x0, passGas) - mstore(0x20, auxDataRes) - return(0x0, 0x40) - } - } -} diff --git a/system-contracts/contracts/EvmGasManager.yul b/system-contracts/contracts/EvmGasManager.yul new file mode 100644 index 000000000..957f574b7 --- /dev/null +++ b/system-contracts/contracts/EvmGasManager.yul @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: MIT + +object "EvmGasManager" { + code { + return(0, 0) + } + object "EvmGasManager_deployed" { + code { + function ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008002 + } + + function IS_ACCOUNT_EVM_PREFIX() -> prefix { + prefix := shl(255, 1) + } + + function IS_ACCOUNT_WARM_PREFIX() -> prefix { + prefix := shl(254, 1) + } + + function IS_SLOT_WARM_PREFIX() -> prefix { + prefix := shl(253, 1) + } + + function PRECOMPILES_END() -> value { + value := sub(0xffff, 1) // TODO should we exclude system contracts? + } + + function EVM_GAS_SLOT() -> value { + value := 4 + } + + function EVM_AUX_DATA_SLOT() -> value { + value := 5 + } + + function EVM_ACTIVE_FRAME_FLAG() -> value { + value := 2 + } + + function EVM_STATIC_FLAG() -> value { + value := 1 + } + + function ADDRESS_MASK() -> mask { + mask := sub(shl(160, 1), 1) + } + + function $llvm_AlwaysInline_llvm$__getRawSenderCodeHash() -> hash { + mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) + mstore(4, caller()) + + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + returndatacopy(0, 0, 32) + hash := mload(0) + } + + /// @dev Checks that the call is done by the EVM emulator in system mode. + function $llvm_AlwaysInline_llvm$_onlyEvmSystemCall() { + let callFlags := verbatim_0i_1o("get_global::call_flags") + let notSystemCall := iszero(and(callFlags, 2)) + + if notSystemCall { + revert(0, 0) // TODO errors? + } + + // SELFDESTRUCT is not supported, so it is ok to cache here + let transientSlot := or(IS_ACCOUNT_EVM_PREFIX(), caller()) + let isEVM := tload(transientSlot) + if iszero(isEVM) { + let versionedCodeHash := $llvm_AlwaysInline_llvm$__getRawSenderCodeHash() + isEVM := eq(shr(248, versionedCodeHash), 2) + + if iszero(isEVM) { + revert(0, 0) + } + + // we will not cache contract if it is being constructed + let isContractConstructed := iszero(and(0xFF, shr(240, versionedCodeHash))) + if isContractConstructed { + tstore(transientSlot, 1) + } + } + } + + //////////////////////////////////////////////////////////////// + // FALLBACK + //////////////////////////////////////////////////////////////// + + let _calldata0Slot := calldataload(0) + + // Please note that we do not use the standard solidity calldata encoding here. + // This allows us to optimize the contract and reduce overhead. + // We use 1 byte as selector, arguments can be packed, the size of the returned data may vary. + let functionSelector := shr(248, _calldata0Slot) + switch functionSelector + case 0 { // function warmAccount(address account) + // Warm account, if needed. If it is already warm, will return 32 bytes of unspecified data. + // Account address should be packed in one 32-bytes word with selector. + $llvm_AlwaysInline_llvm$_onlyEvmSystemCall() + + let account := and(ADDRESS_MASK(), _calldata0Slot) + + let wasWarm := true + + if gt(account, PRECOMPILES_END()) { + let transientSlot := or(IS_ACCOUNT_WARM_PREFIX(), account) + wasWarm := tload(transientSlot) + + if iszero(wasWarm) { + tstore(transientSlot, 1) + } + } + + if wasWarm { + return(0x0, 0x20) + } + return(0x0, 0x0) + } + case 1 { // function isSlotWarm(uint256 _slot) + // If specified slot in the caller storage is warm, will return 32 bytes of unspecified data. + mstore(0, calldataload(1)) // load _slot + mstore(32, or(IS_SLOT_WARM_PREFIX(), caller())) // prefixed caller address + + let transientSlot := keccak256(0, 64) + + if tload(transientSlot) { + return(0x0, 0x20) + } + return(0x0, 0x0) + } + case 2 { // function warmSlot(uint256 _slot, uint256 currentValue) + // Warm slot in caller storage, if needed. Will return original value of the slot if it is already warm. + $llvm_AlwaysInline_llvm$_onlyEvmSystemCall() + + mstore(0, calldataload(1)) // load _slot + mstore(32, or(IS_SLOT_WARM_PREFIX(), caller())) // prefixed caller address + + let transientSlot := keccak256(0, 64) + let isWarm := tload(transientSlot) + + if isWarm { + let originalValue := tload(add(transientSlot, 1)) + mstore(0x0, originalValue) + return(0x0, 0x20) + } + + let currentValue := calldataload(33) + tstore(transientSlot, 1) + tstore(add(transientSlot, 1), currentValue) + return(0x0, 0x0) + } + case 3 { // function pushEVMFrame(bool isStatic, uint256 passGas) + // Save EVM frame context data + // This method is used by EvmEmulator to save new frame context data for external call. + // isStatic flag should be packed in one 32-bytes word with selector. + $llvm_AlwaysInline_llvm$_onlyEvmSystemCall() + let isStatic := and(_calldata0Slot, 1) + let passGas := calldataload(32) + tstore(EVM_GAS_SLOT(), passGas) + tstore(EVM_AUX_DATA_SLOT(), or(isStatic, EVM_ACTIVE_FRAME_FLAG())) // mark frame as active + return(0x0, 0x0) + } + case 4 { // function consumeEvmFrame() + // This method is used by EvmEmulator to get context data. + // If the frame is active, 32 bytes of unspecified data will be returned. + // If the frame is active and is static, 64 bytes of unspecified data will be returned. + $llvm_AlwaysInline_llvm$_onlyEvmSystemCall() + + let auxData := tload(EVM_AUX_DATA_SLOT()) + + let isFrameActive := and(auxData, EVM_ACTIVE_FRAME_FLAG()) + if isFrameActive { + tstore(EVM_AUX_DATA_SLOT(), 0) // mark as consumed + + let passGas := tload(EVM_GAS_SLOT()) + mstore(0x0, passGas) + + let isStatic := and(auxData, EVM_STATIC_FLAG()) + if isStatic { + return(0x0, 0x40) + } + return(0x0, 0x20) + } + + // We do not have active frame. This means that the EVM contract was called from the EraVM contract. + // We should mark the EVM contract as warm. + let isSenderWarmSlot := or(IS_ACCOUNT_WARM_PREFIX(), caller()) + tstore(isSenderWarmSlot, 1) + return(0x0, 0x0) + } + default { + revert(0, 0) + } + } + } +} diff --git a/system-contracts/contracts/interfaces/IEvmGasManager.sol b/system-contracts/contracts/interfaces/IEvmGasManager.sol deleted file mode 100644 index 646d7bf24..000000000 --- a/system-contracts/contracts/interfaces/IEvmGasManager.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -interface IEvmGasManager { - 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); - - function pushEVMFrame(uint256 _passGas, bool _isStatic) external payable; - - function consumeEvmFrame() external payable returns (uint256 passGas, uint256 auxData); -} diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 032a83e8d..5c0cd92e8 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -287,13 +287,14 @@ function getDeployedBytecode() { function consumeEvmFrame() -> passGas, isStatic, callerEVM { // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) - mstore(0, 0x04C14E9E00000000000000000000000000000000000000000000000000000000) + // non-standard selector 0x04 + mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) let farCallAbi := getFarCallABI( 0, 0, 0, - 4, + 1, gas(), // Only rollup is supported for now 0, @@ -309,14 +310,14 @@ function consumeEvmFrame() -> passGas, isStatic, callerEVM { revert(0, 0) } - returndatacopy(0,0,64) + let _returndatasize := returndatasize() + if _returndatasize { + callerEVM := true - let auxData := mload(32) - callerEVM := gt(auxData, 1) - - if callerEVM { - isStatic := and(auxData, 1) + returndatacopy(0, 0, 32) passGas := mload(0) + + isStatic := gt(_returndatasize, 32) } } @@ -522,29 +523,33 @@ function expandMemory(newSize) -> gasCost { } function isSlotWarm(key) -> isWarm { - mstore(0, 0x482D2E7400000000000000000000000000000000000000000000000000000000) - mstore(4, key) + // non-standard selector 0x01 + mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 36, 0, 32) + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } - isWarm := mload(0) + if returndatasize() { + isWarm := true + } } function warmSlot(key,currentValue) -> isWarm, originalValue { - mstore(0, 0xBDF7816000000000000000000000000000000000000000000000000000000000) - mstore(4, key) - mstore(36,currentValue) + // non-standard selector 0x02 + mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) + mstore(33,currentValue) let farCallAbi := getFarCallABI( 0, 0, 0, - 68, + 65, gas(), // Only rollup is supported for now 0, @@ -560,10 +565,11 @@ function warmSlot(key,currentValue) -> isWarm, originalValue { revert(0, 0) } - returndatacopy(0, 0, 64) - - isWarm := mload(0) - originalValue := mload(32) + if returndatasize() { + isWarm := true + returndatacopy(0, 0, 32) + originalValue := mload(0) + } } function getFarCallABI( @@ -604,14 +610,16 @@ function addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) -> newOffset,newS } function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { - mstore(0, 0x8DB2BA7800000000000000000000000000000000000000000000000000000000) - mstore(4, addr) + // function warmAccount(address account) + // non-standard selector 0x00 + // addr is packed in the same word with selector + mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) let farCallAbi := getFarCallABI( 0, 0, 0, - 36, + 32, gas(), // Only rollup is supported for now 0, @@ -627,8 +635,9 @@ function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { revert(0, 0) } - returndatacopy(0, 0, 32) - isWarm := mload(0) + if returndatasize() { + isWarm := true + } } function getRawNonce(addr) -> nonce { @@ -665,17 +674,16 @@ function _isEVM(_addr) -> isEVM { } function _pushEVMFrame(_passGas, _isStatic) { - // function pushEVMFrame(uint256 _passGas, bool _isStatic) external - - mstore(0, 0xEAD7715600000000000000000000000000000000000000000000000000000000) - mstore(4, _passGas) - mstore(36, _isStatic) + // function pushEVMFrame + // non-standard selector 0x03 + mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) + mstore(32, _passGas) let farCallAbi := getFarCallABI( 0, 0, 0, - 68, + 64, gas(), // Only rollup is supported for now 0, From a3254c8fc491bac8cd49acd42f3848772465a582 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 18 Oct 2024 15:25:21 +0200 Subject: [PATCH 077/183] fix: Fix bootloader bytecode loading after new `zksolc` version (#949) --- system-contracts/scripts/deploy-preimages.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system-contracts/scripts/deploy-preimages.ts b/system-contracts/scripts/deploy-preimages.ts index 69ebdd49c..8704251ac 100644 --- a/system-contracts/scripts/deploy-preimages.ts +++ b/system-contracts/scripts/deploy-preimages.ts @@ -196,7 +196,7 @@ class ZkSyncDeployer { } async processBootloader() { - const bootloaderCode = readBytecodeUtf8("./bootloader/build/artifacts/proved_batch.yul.zbin"); + const bootloaderCode = readBytecodeUtf8("./bootloader/build/artifacts/proved_batch.yul/proved_batch.yul.zbin"); await this.publishBootloader(bootloaderCode); await this.checkShouldUpgradeBootloader(bootloaderCode); From 91bc660558415f154f02c5e0e3953c0a3b81c198 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 18 Oct 2024 16:03:02 +0200 Subject: [PATCH 078/183] fix(EVM): Fix scripts (#950) Signed-off-by: Danil Co-authored-by: kelemeno <34402761+kelemeno@users.noreply.github.com> Co-authored-by: Danil Co-authored-by: Vlad Bochok <41153528+vladbochok@users.noreply.github.com> --- l1-contracts/scripts/utils.ts | 4 +++- system-contracts/hardhat.config.ts | 1 + system-contracts/scripts/deploy-preimages.ts | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/l1-contracts/scripts/utils.ts b/l1-contracts/scripts/utils.ts index a9cbdacd1..b86be8e15 100644 --- a/l1-contracts/scripts/utils.ts +++ b/l1-contracts/scripts/utils.ts @@ -77,7 +77,9 @@ export function readSystemContractsBytecode(fileName: string) { export function readEvmEmulatorbytecode() { const systemContractsPath = path.join(process.env.ZKSYNC_HOME as string, "contracts/system-contracts"); - return fs.readFileSync(`${systemContractsPath}/contracts-preprocessed/artifacts/EvmEmulator.yul.zbin`); + return readBytecodeUtf8( + `${systemContractsPath}/contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin` + ); } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/system-contracts/hardhat.config.ts b/system-contracts/hardhat.config.ts index 3b03302c8..5a6ab2986 100644 --- a/system-contracts/hardhat.config.ts +++ b/system-contracts/hardhat.config.ts @@ -5,6 +5,7 @@ import "@matterlabs/hardhat-zksync-verify"; import "@nomiclabs/hardhat-ethers"; import "hardhat-typechain"; +// This version of system contracts requires a pre release of the compiler const COMPILER_VERSION = "v1.5.6"; const PRE_RELEASE_VERSION = "1.5.6"; function getZksolcUrl(): string { diff --git a/system-contracts/scripts/deploy-preimages.ts b/system-contracts/scripts/deploy-preimages.ts index 719607916..5ff77ce76 100644 --- a/system-contracts/scripts/deploy-preimages.ts +++ b/system-contracts/scripts/deploy-preimages.ts @@ -246,7 +246,7 @@ class ZkSyncDeployer { } async processBootloader() { - const bootloaderCode = readBytecodeUtf8("./bootloader/build/artifacts/proved_batch.yul.zbin"); + const bootloaderCode = readBytecodeUtf8("./bootloader/build/artifacts/proved_batch.yul/proved_batch.yul.zbin"); await this.publishBootloader(bootloaderCode); await this.checkShouldUpgradeBootloader(bootloaderCode); From 8bc5e7a2aee82490e107668e400fe0ae9831d625 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 21 Oct 2024 14:23:25 +0200 Subject: [PATCH 079/183] fix(EVM): Fix known code storage (#953) --- system-contracts/SystemContractsHashes.json | 4 ++-- system-contracts/contracts/KnownCodesStorage.sol | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 0615c2792..eb2901077 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -66,8 +66,8 @@ "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000c1242abf7683aa2be6c873109d418e5e1fd76d8a54a27d30248fbcdb4f", - "sourceCodeHash": "0xd19ebf4cf153de38a62229e4663b73fbeaaa7195527eb9ebb07214ce4c6751ea" + "bytecodeHash": "0x010000c16012ea2c31038b2a944f7d5d0b4192a61074555068a6bed5978cd481", + "sourceCodeHash": "0xeb83e3a2ea2f50b93122363b8dd56fbcfe821d11723d849eecbde3d6af1147de" }, { "contractName": "L1Messenger", diff --git a/system-contracts/contracts/KnownCodesStorage.sol b/system-contracts/contracts/KnownCodesStorage.sol index d0d8bcae0..0bbaeeb17 100644 --- a/system-contracts/contracts/KnownCodesStorage.sol +++ b/system-contracts/contracts/KnownCodesStorage.sol @@ -104,7 +104,7 @@ contract KnownCodesStorage is IKnownCodesStorage, SystemContractBase { sstore(vesionedBytecodeHash, 1) } - emit MarkedAsKnown(vesionedBytecodeHash, true); + emit MarkedAsKnown(vesionedBytecodeHash, false); } assembly { From e542fdfcb86ff20380a6bba53f0c6afc4e75e09c Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 21 Oct 2024 18:57:41 +0200 Subject: [PATCH 080/183] feat(EVM): Add Identity precompile (#956) --- system-contracts/SystemContractsHashes.json | 37 +++++++++++-------- system-contracts/contracts/Constants.sol | 1 + .../contracts/precompiles/Identity.yul | 24 ++++++++++++ .../test/precompiles/Identity.spec.ts | 19 ++++++++++ 4 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 system-contracts/contracts/precompiles/Identity.yul create mode 100644 system-contracts/test/precompiles/Identity.spec.ts diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index eb2901077..c066de88a 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": "0x0100007723fbe7d5aa0b9eafd79b3e776b290726254b7bfda267c8fe63480703", + "bytecodeHash": "0x010000770d1ad5dccb505d6d550d688408f162f13bde5dab6628b9739c1507ae", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f1e17b338570641527be4a4548b80b8c6dff188959c253842b115be17b", + "bytecodeHash": "0x010006f14b3e5ab60d5e53b4ef8d08e5abc0bdfba461705d3bf8ddf37cf42b8e", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x01000047d537ae233868d05129ce4c590032c489b4cf07c96e5b9d9a0f6507c9", + "bytecodeHash": "0x01000047067f0bd2667d64ac7edd106c5c6a40fb287b70314984dd6e32ba6be1", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013f6b31caf9414e0e55165a527d2ec0ae05dbd9ce6cc1515609e971f31f", + "bytecodeHash": "0x0100013f6a3a7d0769f64451d185895c3a839047c1400bfedae19b03ee8a1cf3", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010005c167a5031dcd06144c2b9ea1625927317e754847f977f5cdc120c3b11a", + "bytecodeHash": "0x010005c16efab28191218d32be99762e38165e1278b1341fd6f4fda67a52023e", "sourceCodeHash": "0x8fecd5c1284ade078f91ba270a2c0a96e91475861cceff7304d17469fd8e0ef2" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003f7cdb25550a4f1aeb5273582f52ea4009c732891d0dfe77f0cf1ba0d8", + "bytecodeHash": "0x0100003f0719fa16f261fff54d3b54e99538342210f6048c97f51a32abcda54b", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x01000503285b02130b8fc5d7bd876650285a4224988605ee8171cf48f2856f1a", + "bytecodeHash": "0x01000503995a56fbbabfd01df28d096f83ad1ebe9c5b2943782fdacec930f141", "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { @@ -59,56 +59,56 @@ "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033e5376655c78111a162af76c4123514d6a1c674c546c5b8743932a66b", + "bytecodeHash": "0x01000033006022a456ca30686147e715d6eaa743f5b735c3de6c320e471a04b6", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000c16012ea2c31038b2a944f7d5d0b4192a61074555068a6bed5978cd481", + "bytecodeHash": "0x010000c1e4010651c2ef7aac70beb479d68dc23272349289693718dbb7545a91", "sourceCodeHash": "0xeb83e3a2ea2f50b93122363b8dd56fbcfe821d11723d849eecbde3d6af1147de" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010002655f6300e6727889907b9bca66a8860c5c2856efd6255dfce087cce9f7", + "bytecodeHash": "0x010002659c6c2e6e0e44a99ec4b4b6c69ff8ca0d6c2b9be0de28d687fdc20140", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f3ce3bf50b3f959d587f3cc85459bea4b72de6f9bd74ec73f4b71f1d30", + "bytecodeHash": "0x010000f36ab487155ade735537ce9aac7e0c231d1f52653851de4bc905cf9769", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x010000593cbabdacfca62483f479a180f4ea05e228897f1d242e278beda54d16", + "bytecodeHash": "0x01000059d2e4402d061635ca1ee1a28d2759f452536ba86aefd9add8a7267b5a", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cf6010047bbbb07094e62a6e5d3118b43ffe774b3ab280d8b1e0459082", + "bytecodeHash": "0x010000cf93373b31cda60ce1ae9eeb9c0b7185b4b9dd4ee44f0d51f0983f13f5", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x010000413ab00a975878979e83557ce0d8c96d896d69df966bba03d74b60efa5", + "bytecodeHash": "0x01000041c0b7009011f319f2119be4aa438ad575e3ef9c250d6b309242bf18ba", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a509d4a68571775f2c1a7fbe82842da52c6c8794e10af47723f6b0964c", + "bytecodeHash": "0x010001a516977d7a6f0bd69e75da6d4d9ff179faf0318fd86cb91fcfb09f3c69", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { @@ -167,6 +167,13 @@ "bytecodeHash": "0x01000013ffc212bb76a7b9108abff6be1d0746154e36d32e9c69268ef95e556a", "sourceCodeHash": "0x21e03ab7a5f518a21258669c82506b1d4d1141f8fd4f30bb385f9730580ddd3c" }, + { + "contractName": "Identity", + "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Identity.yul/Identity.yul.zbin", + "sourceCodePath": "contracts-preprocessed/precompiles/Identity.yul", + "bytecodeHash": "0x0100000d3cc11217da589db87c1cb3fda76701b7923b334b465eafd2e018b1b1", + "sourceCodeHash": "0xcdf59308c83593ed41d9742411fdf41cfd9863932f948d20d08a11f6dcbd8f46" + }, { "contractName": "Keccak256", "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Keccak256.yul/Keccak256.yul.zbin", diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index 20858729a..4fba3d615 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -30,6 +30,7 @@ uint160 constant MAX_SYSTEM_CONTRACT_ADDRESS = 0xffff; // 2^16 - 1 address constant ECRECOVER_SYSTEM_CONTRACT = address(0x01); address constant SHA256_SYSTEM_CONTRACT = address(0x02); +address constant IDENTITY_SYSTEM_CONTRACT = address(0x04); address constant ECADD_SYSTEM_CONTRACT = address(0x06); address constant ECMUL_SYSTEM_CONTRACT = address(0x07); address constant ECPAIRING_SYSTEM_CONTRACT = address(0x08); diff --git a/system-contracts/contracts/precompiles/Identity.yul b/system-contracts/contracts/precompiles/Identity.yul new file mode 100644 index 000000000..2e35975f3 --- /dev/null +++ b/system-contracts/contracts/precompiles/Identity.yul @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT + +/** + * @author Matter Labs + * @custom:security-contact security@matterlabs.dev + * @notice The contract used to support legacy MCOPY operations + * @dev It simply returns the calldata. + */ + object "Identity" { + code { + return(0, 0) + } + object "Identity_deployed" { + code { + //////////////////////////////////////////////////////////////// + // FALLBACK + //////////////////////////////////////////////////////////////// + + let size := calldatasize() + calldatacopy(0, 0, size) + return(0, size) + } + } +} diff --git a/system-contracts/test/precompiles/Identity.spec.ts b/system-contracts/test/precompiles/Identity.spec.ts new file mode 100644 index 000000000..7c74550ca --- /dev/null +++ b/system-contracts/test/precompiles/Identity.spec.ts @@ -0,0 +1,19 @@ +import { expect } from "chai"; +import type { Contract } from "zksync-ethers"; +import { callFallback, deployContractYul } from "../shared/utils"; + +describe.only("EcAdd tests", function () { + let identity: Contract; + + before(async () => { + identity = await deployContractYul("Identity", "precompiles"); + }); + + describe("Ethereum tests", function () { + it("Returns data", async () => { + const data = "0xff00ff00ff00ff00ff"; + const returnData = await callFallback(identity, data); + expect(returnData).to.be.equal(data); + }); + }); +}); From 1c3c818f5d10f6e601a6726e35c786215a775d76 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 22 Oct 2024 12:01:33 +0200 Subject: [PATCH 081/183] fix(EVM): Refactor calls (#958) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 690 ++++++++---------- .../EvmEmulatorFunctions.template.yul | 308 ++++---- .../evm-emulator/EvmEmulatorLoop.template.yul | 37 +- 4 files changed, 440 insertions(+), 599 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index c066de88a..697ec4375 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000dcdf3a70d93ce630d6607b87e6ca013819bb2b67cfd2d544c31c21dcce7", - "sourceCodeHash": "0x6b27cc953993aef0a2b009b5bcd67b9a6f738fcfa927ff40706e7ef9d66126c0" + "bytecodeHash": "0x01000da9de9056e6d87615b5f76bf4602c78f34b763452612dd5d0af6cd88f1b", + "sourceCodeHash": "0x2c951c86f5704857f1457b609a5985458dba815c8a0f1f8f0d8cf8108dde60b6" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 95e5f5361..beaaff9f5 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -761,7 +761,7 @@ object "EvmEmulator" { function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 function _calcEVMGas(_zkevmGas) -> calczkevmGas { - calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) + calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) // TODO round up } function getEVMGas() -> evmGas { @@ -836,12 +836,32 @@ object "EvmEmulator" { mstore(lastRtSzOffset, returndatasize()) } - function performStaticCall(oldSp,evmGasLeft) -> extraCost, sp { - let gasToPass,addr, argsOffset, argsSize, retOffset, retSize + function capGas(evmGasLeft,oldGasToPass) -> gasToPass { + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + gasToPass := oldGasToPass + if gt(oldGasToPass, maxGasToPass) { + gasToPass := maxGasToPass + } + } - popStackCheck(oldSp, evmGasLeft, 6) + function getMaxMemoryExpansionCost(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(oldSp, evmGasLeft) -> newGasLeft, 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) @@ -849,129 +869,75 @@ object "EvmEmulator" { addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + checkOverflow(argsOffset,argsSize, evmGasLeft) checkOverflow(retOffset, retSize, evmGasLeft) checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) - extraCost := 0 + // 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. + + let gasUsed := 100 // warm address access cost if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - extraCost := 2500 + gasUsed := 2600 // cold address access cost } - { - let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) - extraCost := add(extraCost,maxExpand) + if gt(value, 0) { + gasUsed := add(gasUsed, 6700) // positive_value_cost - stipend + gasToPass := add(gasToPass, 2300) // stipend TODO + + if isAddrEmpty(addr) { + gasUsed := add(gasUsed, 25000) // value_to_empty_account_cost + } } - let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 - if gt(gasToPass, maxGasToPass) { - gasToPass := maxGasToPass + + { + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + gasUsed := add(gasUsed, maxExpand) } - 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() + evmGasLeft := chargeGas(evmGasLeft, gasUsed) - let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + gasToPass := capGas(evmGasLeft, gasToPass) - 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) + let success, frameGasLeft := _performCall( + addr, + gasToPass, + value, + add(argsOffset, MEM_OFFSET_INNER()), + argsSize, + add(retOffset, MEM_OFFSET_INNER()), + retSize + ) - frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - } + let gasUsed := 0 + // TODO precompile should be called, but return nothing if gasPassed is too low let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) switch iszero(precompileCost) case 1 { - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + gasUsed := sub(gasToPass, frameGasLeft) } default { - extraCost := add(extraCost, precompileCost) + gasUsed := 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) - } - } - default { - if value { - revertWithGas(gasToPassNew) - } - success, frameGasLeft:= _performStaticCall( - is_evm, - gasToPassNew, - addr, - argsOffset, - argsSize, - retOffset, - retSize - ) - } + newGasLeft := chargeGas(evmGasLeft, gasUsed) + sp := pushStackItem(sp, success, newGasLeft) } - function performCall(oldSp, evmGasLeft, isStatic) -> extraCost, sp { - let gasToPass,addr,value,argsOffset,argsSize,retOffset,retSize + function performStaticCall(oldSp, evmGasLeft) -> newEvmGasLeft, sp { + let gasToPass,addr, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 7) + popStackCheck(oldSp, evmGasLeft, 6) gasToPass, sp := popStackItemWithoutCheck(oldSp) addr, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) argsOffset, sp := popStackItemWithoutCheck(sp) argsSize, sp := popStackItemWithoutCheck(sp) retOffset, sp := popStackItemWithoutCheck(sp) @@ -979,72 +945,55 @@ object "EvmEmulator" { 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. + checkOverflow(argsOffset,argsSize, evmGasLeft) + checkOverflow(retOffset, retSize, evmGasLeft) - extraCost := 0 - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - extraCost := 2500 - } + checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) - if gt(value, 0) { - extraCost := add(extraCost,6700) - gasToPass := add(gasToPass,2300) + let gasUsed := 100 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + gasUsed := 2600 } - if and(isAddrEmpty(addr), gt(value, 0)) { - extraCost := add(extraCost,25000) - } { - let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) - extraCost := add(extraCost,maxExpand) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + gasUsed := add(gasUsed, maxExpand) } - gasToPass := capGas(evmGasLeft,gasToPass) - argsOffset := add(argsOffset,MEM_OFFSET_INNER()) - retOffset := add(retOffset,MEM_OFFSET_INNER()) + evmGasLeft := chargeGas(evmGasLeft, gasUsed) - checkOverflow(argsOffset,argsSize, evmGasLeft) - checkOverflow(retOffset,retSize, evmGasLeft) - - checkMemOverflow(add(argsOffset, argsSize), evmGasLeft) - checkMemOverflow(add(retOffset, retSize), evmGasLeft) + gasToPass := capGas(evmGasLeft, gasToPass) - let success, frameGasLeft - success, frameGasLeft, gasToPass:= _performCall( + let success, frameGasLeft := _performStaticCall( addr, gasToPass, - value, - argsOffset, + add(MEM_OFFSET_INNER(), argsOffset), argsSize, - retOffset, - retSize, - isStatic + add(MEM_OFFSET_INNER(), retOffset), + retSize ) + let gasUsed := 0 + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) switch iszero(precompileCost) case 1 { - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + gasUsed := sub(gasToPass, frameGasLeft) } default { - extraCost := add(extraCost, precompileCost) + gasUsed := precompileCost } - sp := pushStackItem(sp,success, evmGasLeft) + + newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + sp := pushStackItem(sp, success, newEvmGasLeft) } - function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost { + function performDelegateCall(oldSp, evmGasLeft, isStatic) -> newEvmGasLeft, sp { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize - sp := oldSp - isStatic := oldIsStatic - - popStackCheck(sp, evmGasLeft, 6) - gasToPass, sp := popStackItemWithoutCheck(sp) + popStackCheck(oldSp, evmGasLeft, 6) + gasToPass, sp := popStackItemWithoutCheck(oldSp) addr, sp := popStackItemWithoutCheck(sp) argsOffset, sp := popStackItemWithoutCheck(sp) argsSize, sp := popStackItemWithoutCheck(sp) @@ -1063,16 +1012,19 @@ object "EvmEmulator" { revertWithGas(evmGasLeft) } - extraCost := 0 + let gasUsed := 100 if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - extraCost := 2500 + gasUsed := 2600 } { - let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) - extraCost := add(extraCost,maxExpand) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + gasUsed := add(gasUsed, maxExpand) } - gasToPass := capGas(evmGasLeft,gasToPass) + + evmGasLeft := chargeGas(evmGasLeft, gasUsed) + + gasToPass := capGas(evmGasLeft, gasToPass) _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( @@ -1086,48 +1038,52 @@ object "EvmEmulator" { ) let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + let gasUsed := sub(gasToPass, frameGasLeft) - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - switch iszero(precompileCost) - case 1 { - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + + sp := pushStackItem(sp, success, newEvmGasLeft) + } + + function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + switch _isEVM(addr) + case 0 { + // zkEVM native + let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) + let zkEvmGasBefore := gas() + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) + + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) // TODO check + } } default { - extraCost := add(extraCost, precompileCost) + _pushEVMFrame(gasToPass, false) + success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } - sp := pushStackItem(sp, success, evmGasLeft) } - function _performStaticCall( - _calleeIsEVM, - _calleeGas, - _callee, - _inputOffset, - _inputLen, - _outputOffset, - _outputLen - ) -> success, _gasLeft { - switch _calleeIsEVM + function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + switch _isEVM(addr) case 0 { // zkEVM native - _calleeGas := _getZkEVMGas(_calleeGas, _callee) - let zkevmGasBefore := gas() - success := staticcall(_calleeGas, _callee, _inputOffset, _inputLen, _outputOffset, _outputLen) - + let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) + let zkEvmGasBefore := gas() + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() + let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) - let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) - - _gasLeft := 0 - if gt(_calleeGas, gasUsed) { - _gasLeft := sub(_calleeGas, gasUsed) + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) // TODO check } } default { - _pushEVMFrame(_calleeGas, true) - success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) - - _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) + _pushEVMFrame(gasToPass, true) + success := staticcall(EVM_GAS_STIPEND(), addr, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } @@ -1301,7 +1257,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { - revertWithGas(evmGasLeft) + revertWithGas(evmGasLeft) // TODO review } let value, offset, size @@ -2774,28 +2730,28 @@ object "EvmEmulator" { 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) + switch isStatic + case 0 { + evmGasLeft, sp := performCall(sp, evmGasLeft) + } + default { + evmGasLeft, sp := performStaticCall(sp, evmGasLeft) + } + ip := add(ip, 1) } case 0xF3 { // OP_RETURN - let offset,size + 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))) + checkOverflow(offset, size, evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) - checkMemOverflowByOffset(add(offset,size), evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) returnLen := size @@ -2804,12 +2760,7 @@ object "EvmEmulator" { break } case 0xF4 { // OP_DELEGATECALL - evmGasLeft := chargeGas(evmGasLeft, 100) - - let gasUsed - sp, isStatic, gasUsed := delegateCall(sp, isStatic, evmGasLeft) - - evmGasLeft := chargeGas(evmGasLeft, gasUsed) + evmGasLeft, sp := performDelegateCall(sp, evmGasLeft, isStatic) ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 @@ -2821,11 +2772,7 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0xFA { // OP_STATICCALL - evmGasLeft := chargeGas(evmGasLeft, 100) - - let gasUsed - gasUsed, sp := performStaticCall(sp,evmGasLeft) - evmGasLeft := chargeGas(evmGasLeft,gasUsed) + evmGasLeft, sp := performStaticCall(sp, evmGasLeft) ip := add(ip, 1) } case 0xFD { // OP_REVERT @@ -3605,7 +3552,7 @@ object "EvmEmulator" { function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 function _calcEVMGas(_zkevmGas) -> calczkevmGas { - calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) + calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) // TODO round up } function getEVMGas() -> evmGas { @@ -3680,12 +3627,32 @@ object "EvmEmulator" { mstore(lastRtSzOffset, returndatasize()) } - function performStaticCall(oldSp,evmGasLeft) -> extraCost, sp { - let gasToPass,addr, argsOffset, argsSize, retOffset, retSize + function capGas(evmGasLeft,oldGasToPass) -> gasToPass { + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + gasToPass := oldGasToPass + if gt(oldGasToPass, maxGasToPass) { + gasToPass := maxGasToPass + } + } - popStackCheck(oldSp, evmGasLeft, 6) + function getMaxMemoryExpansionCost(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(oldSp, evmGasLeft) -> newGasLeft, 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) @@ -3693,129 +3660,75 @@ object "EvmEmulator" { addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + checkOverflow(argsOffset,argsSize, evmGasLeft) checkOverflow(retOffset, retSize, evmGasLeft) checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) - extraCost := 0 + // 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. + + let gasUsed := 100 // warm address access cost if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - extraCost := 2500 + gasUsed := 2600 // cold address access cost } - { - let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) - extraCost := add(extraCost,maxExpand) + if gt(value, 0) { + gasUsed := add(gasUsed, 6700) // positive_value_cost - stipend + gasToPass := add(gasToPass, 2300) // stipend TODO + + if isAddrEmpty(addr) { + gasUsed := add(gasUsed, 25000) // value_to_empty_account_cost + } } - let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 - if gt(gasToPass, maxGasToPass) { - gasToPass := maxGasToPass + + { + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + gasUsed := add(gasUsed, maxExpand) } - 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() + evmGasLeft := chargeGas(evmGasLeft, gasUsed) - let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + gasToPass := capGas(evmGasLeft, gasToPass) - 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) + let success, frameGasLeft := _performCall( + addr, + gasToPass, + value, + add(argsOffset, MEM_OFFSET_INNER()), + argsSize, + add(retOffset, MEM_OFFSET_INNER()), + retSize + ) - frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - } + let gasUsed := 0 + // TODO precompile should be called, but return nothing if gasPassed is too low let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) switch iszero(precompileCost) case 1 { - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + gasUsed := sub(gasToPass, frameGasLeft) } default { - extraCost := add(extraCost, precompileCost) + gasUsed := 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 - } + newGasLeft := chargeGas(evmGasLeft, gasUsed) + sp := pushStackItem(sp, success, newGasLeft) } - 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) - } - } - 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 + function performStaticCall(oldSp, evmGasLeft) -> newEvmGasLeft, sp { + let gasToPass,addr, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 7) + popStackCheck(oldSp, evmGasLeft, 6) gasToPass, sp := popStackItemWithoutCheck(oldSp) addr, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) argsOffset, sp := popStackItemWithoutCheck(sp) argsSize, sp := popStackItemWithoutCheck(sp) retOffset, sp := popStackItemWithoutCheck(sp) @@ -3823,72 +3736,55 @@ object "EvmEmulator" { 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. + checkOverflow(argsOffset,argsSize, evmGasLeft) + checkOverflow(retOffset, retSize, evmGasLeft) - extraCost := 0 - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - extraCost := 2500 - } + checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) - if gt(value, 0) { - extraCost := add(extraCost,6700) - gasToPass := add(gasToPass,2300) + let gasUsed := 100 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + gasUsed := 2600 } - if and(isAddrEmpty(addr), gt(value, 0)) { - extraCost := add(extraCost,25000) - } { - let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) - extraCost := add(extraCost,maxExpand) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + gasUsed := add(gasUsed, 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) + evmGasLeft := chargeGas(evmGasLeft, gasUsed) - checkMemOverflow(add(argsOffset, argsSize), evmGasLeft) - checkMemOverflow(add(retOffset, retSize), evmGasLeft) + gasToPass := capGas(evmGasLeft, gasToPass) - let success, frameGasLeft - success, frameGasLeft, gasToPass:= _performCall( + let success, frameGasLeft := _performStaticCall( addr, gasToPass, - value, - argsOffset, + add(MEM_OFFSET_INNER(), argsOffset), argsSize, - retOffset, - retSize, - isStatic + add(MEM_OFFSET_INNER(), retOffset), + retSize ) + let gasUsed := 0 + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) switch iszero(precompileCost) case 1 { - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + gasUsed := sub(gasToPass, frameGasLeft) } default { - extraCost := add(extraCost, precompileCost) + gasUsed := precompileCost } - sp := pushStackItem(sp,success, evmGasLeft) + + newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + sp := pushStackItem(sp, success, newEvmGasLeft) } - function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost { + function performDelegateCall(oldSp, evmGasLeft, isStatic) -> newEvmGasLeft, sp { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize - sp := oldSp - isStatic := oldIsStatic - - popStackCheck(sp, evmGasLeft, 6) - gasToPass, sp := popStackItemWithoutCheck(sp) + popStackCheck(oldSp, evmGasLeft, 6) + gasToPass, sp := popStackItemWithoutCheck(oldSp) addr, sp := popStackItemWithoutCheck(sp) argsOffset, sp := popStackItemWithoutCheck(sp) argsSize, sp := popStackItemWithoutCheck(sp) @@ -3907,16 +3803,19 @@ object "EvmEmulator" { revertWithGas(evmGasLeft) } - extraCost := 0 + let gasUsed := 100 if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - extraCost := 2500 + gasUsed := 2600 } { - let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) - extraCost := add(extraCost,maxExpand) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + gasUsed := add(gasUsed, maxExpand) } - gasToPass := capGas(evmGasLeft,gasToPass) + + evmGasLeft := chargeGas(evmGasLeft, gasUsed) + + gasToPass := capGas(evmGasLeft, gasToPass) _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( @@ -3930,48 +3829,52 @@ object "EvmEmulator" { ) let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + let gasUsed := sub(gasToPass, frameGasLeft) - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - switch iszero(precompileCost) - case 1 { - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + + sp := pushStackItem(sp, success, newEvmGasLeft) + } + + function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + switch _isEVM(addr) + case 0 { + // zkEVM native + let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) + let zkEvmGasBefore := gas() + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) + + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) // TODO check + } } default { - extraCost := add(extraCost, precompileCost) + _pushEVMFrame(gasToPass, false) + success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } - sp := pushStackItem(sp, success, evmGasLeft) } - function _performStaticCall( - _calleeIsEVM, - _calleeGas, - _callee, - _inputOffset, - _inputLen, - _outputOffset, - _outputLen - ) -> success, _gasLeft { - switch _calleeIsEVM + function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + switch _isEVM(addr) case 0 { // zkEVM native - _calleeGas := _getZkEVMGas(_calleeGas, _callee) - let zkevmGasBefore := gas() - success := staticcall(_calleeGas, _callee, _inputOffset, _inputLen, _outputOffset, _outputLen) - + let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) + let zkEvmGasBefore := gas() + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() + let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) - let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) - - _gasLeft := 0 - if gt(_calleeGas, gasUsed) { - _gasLeft := sub(_calleeGas, gasUsed) + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) // TODO check } } default { - _pushEVMFrame(_calleeGas, true) - success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) - - _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) + _pushEVMFrame(gasToPass, true) + success := staticcall(EVM_GAS_STIPEND(), addr, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } @@ -4145,7 +4048,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { - revertWithGas(evmGasLeft) + revertWithGas(evmGasLeft) // TODO review } let value, offset, size @@ -5618,28 +5521,28 @@ object "EvmEmulator" { 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) + switch isStatic + case 0 { + evmGasLeft, sp := performCall(sp, evmGasLeft) + } + default { + evmGasLeft, sp := performStaticCall(sp, evmGasLeft) + } + ip := add(ip, 1) } case 0xF3 { // OP_RETURN - let offset,size + 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))) + checkOverflow(offset, size, evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) - checkMemOverflowByOffset(add(offset,size), evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) returnLen := size @@ -5648,12 +5551,7 @@ object "EvmEmulator" { break } case 0xF4 { // OP_DELEGATECALL - evmGasLeft := chargeGas(evmGasLeft, 100) - - let gasUsed - sp, isStatic, gasUsed := delegateCall(sp, isStatic, evmGasLeft) - - evmGasLeft := chargeGas(evmGasLeft, gasUsed) + evmGasLeft, sp := performDelegateCall(sp, evmGasLeft, isStatic) ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 @@ -5665,11 +5563,7 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0xFA { // OP_STATICCALL - evmGasLeft := chargeGas(evmGasLeft, 100) - - let gasUsed - gasUsed, sp := performStaticCall(sp,evmGasLeft) - evmGasLeft := chargeGas(evmGasLeft,gasUsed) + evmGasLeft, sp := performStaticCall(sp, evmGasLeft) ip := add(ip, 1) } case 0xFD { // OP_REVERT diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 5c0cd92e8..45fc86b04 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -711,7 +711,7 @@ 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()) + calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) // TODO round up } function getEVMGas() -> evmGas { @@ -786,12 +786,32 @@ function _saveReturndataAfterZkEVMCall() { mstore(lastRtSzOffset, returndatasize()) } -function performStaticCall(oldSp,evmGasLeft) -> extraCost, sp { - let gasToPass,addr, argsOffset, argsSize, retOffset, retSize +function capGas(evmGasLeft,oldGasToPass) -> gasToPass { + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + gasToPass := oldGasToPass + if gt(oldGasToPass, maxGasToPass) { + gasToPass := maxGasToPass + } +} - popStackCheck(oldSp, evmGasLeft, 6) +function getMaxMemoryExpansionCost(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(oldSp, evmGasLeft) -> newGasLeft, 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) @@ -799,129 +819,75 @@ function performStaticCall(oldSp,evmGasLeft) -> extraCost, 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 + // 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. + + let gasUsed := 100 // warm address access cost if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - extraCost := 2500 + gasUsed := 2600 // cold address access cost } - { - let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) - extraCost := add(extraCost,maxExpand) + if gt(value, 0) { + gasUsed := add(gasUsed, 6700) // positive_value_cost - stipend + gasToPass := add(gasToPass, 2300) // stipend TODO + + if isAddrEmpty(addr) { + gasUsed := add(gasUsed, 25000) // value_to_empty_account_cost + } } - let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 - if gt(gasToPass, maxGasToPass) { - gasToPass := maxGasToPass + + { + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + gasUsed := add(gasUsed, maxExpand) } - 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() + evmGasLeft := chargeGas(evmGasLeft, gasUsed) - let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) + gasToPass := capGas(evmGasLeft, gasToPass) - 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) + let success, frameGasLeft := _performCall( + addr, + gasToPass, + value, + add(argsOffset, MEM_OFFSET_INNER()), + argsSize, + add(retOffset, MEM_OFFSET_INNER()), + retSize + ) - frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - } + let gasUsed := 0 + // TODO precompile should be called, but return nothing if gasPassed is too low let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) switch iszero(precompileCost) case 1 { - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + gasUsed := sub(gasToPass, frameGasLeft) } default { - extraCost := add(extraCost, precompileCost) + gasUsed := 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 - } + newGasLeft := chargeGas(evmGasLeft, gasUsed) + sp := pushStackItem(sp, success, newGasLeft) } -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) - } - } - 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 +function performStaticCall(oldSp, evmGasLeft) -> newEvmGasLeft, sp { + let gasToPass,addr, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 7) + popStackCheck(oldSp, evmGasLeft, 6) gasToPass, sp := popStackItemWithoutCheck(oldSp) addr, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) argsOffset, sp := popStackItemWithoutCheck(sp) argsSize, sp := popStackItemWithoutCheck(sp) retOffset, sp := popStackItemWithoutCheck(sp) @@ -929,72 +895,55 @@ function performCall(oldSp, evmGasLeft, isStatic) -> extraCost, 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. + checkOverflow(argsOffset,argsSize, evmGasLeft) + checkOverflow(retOffset, retSize, evmGasLeft) - extraCost := 0 - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - extraCost := 2500 - } + checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) + checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) - if gt(value, 0) { - extraCost := add(extraCost,6700) - gasToPass := add(gasToPass,2300) + let gasUsed := 100 + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + gasUsed := 2600 } - if and(isAddrEmpty(addr), gt(value, 0)) { - extraCost := add(extraCost,25000) - } { - let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) - extraCost := add(extraCost,maxExpand) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + gasUsed := add(gasUsed, 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) + evmGasLeft := chargeGas(evmGasLeft, gasUsed) - checkMemOverflow(add(argsOffset, argsSize), evmGasLeft) - checkMemOverflow(add(retOffset, retSize), evmGasLeft) + gasToPass := capGas(evmGasLeft, gasToPass) - let success, frameGasLeft - success, frameGasLeft, gasToPass:= _performCall( + let success, frameGasLeft := _performStaticCall( addr, gasToPass, - value, - argsOffset, + add(MEM_OFFSET_INNER(), argsOffset), argsSize, - retOffset, - retSize, - isStatic + add(MEM_OFFSET_INNER(), retOffset), + retSize ) + let gasUsed := 0 + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) switch iszero(precompileCost) case 1 { - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + gasUsed := sub(gasToPass, frameGasLeft) } default { - extraCost := add(extraCost, precompileCost) + gasUsed := precompileCost } - sp := pushStackItem(sp,success, evmGasLeft) + + newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + sp := pushStackItem(sp, success, newEvmGasLeft) } -function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost { +function performDelegateCall(oldSp, evmGasLeft, isStatic) -> newEvmGasLeft, sp { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize - sp := oldSp - isStatic := oldIsStatic - - popStackCheck(sp, evmGasLeft, 6) - gasToPass, sp := popStackItemWithoutCheck(sp) + popStackCheck(oldSp, evmGasLeft, 6) + gasToPass, sp := popStackItemWithoutCheck(oldSp) addr, sp := popStackItemWithoutCheck(sp) argsOffset, sp := popStackItemWithoutCheck(sp) argsSize, sp := popStackItemWithoutCheck(sp) @@ -1013,16 +962,19 @@ function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost revertWithGas(evmGasLeft) } - extraCost := 0 + let gasUsed := 100 if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - extraCost := 2500 + gasUsed := 2600 } { - let maxExpand := getMaxExpansionMemory(retOffset,retSize,argsOffset,argsSize) - extraCost := add(extraCost,maxExpand) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + gasUsed := add(gasUsed, maxExpand) } - gasToPass := capGas(evmGasLeft,gasToPass) + + evmGasLeft := chargeGas(evmGasLeft, gasUsed) + + gasToPass := capGas(evmGasLeft, gasToPass) _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( @@ -1036,48 +988,52 @@ function delegateCall(oldSp, oldIsStatic, evmGasLeft) -> sp, isStatic, extraCost ) let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + let gasUsed := sub(gasToPass, frameGasLeft) - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - switch iszero(precompileCost) - case 1 { - extraCost := add(extraCost,sub(gasToPass,frameGasLeft)) + newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + + sp := pushStackItem(sp, success, newEvmGasLeft) +} + +function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + switch _isEVM(addr) + case 0 { + // zkEVM native + let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) + let zkEvmGasBefore := gas() + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) + + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) // TODO check + } } default { - extraCost := add(extraCost, precompileCost) + _pushEVMFrame(gasToPass, false) + success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } - sp := pushStackItem(sp, success, evmGasLeft) } -function _performStaticCall( - _calleeIsEVM, - _calleeGas, - _callee, - _inputOffset, - _inputLen, - _outputOffset, - _outputLen -) -> success, _gasLeft { - switch _calleeIsEVM +function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + switch _isEVM(addr) case 0 { // zkEVM native - _calleeGas := _getZkEVMGas(_calleeGas, _callee) - let zkevmGasBefore := gas() - success := staticcall(_calleeGas, _callee, _inputOffset, _inputLen, _outputOffset, _outputLen) - + let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) + let zkEvmGasBefore := gas() + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() + let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) - let gasUsed := _calcEVMGas(sub(zkevmGasBefore, gas())) - - _gasLeft := 0 - if gt(_calleeGas, gasUsed) { - _gasLeft := sub(_calleeGas, gasUsed) + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) // TODO check } } default { - _pushEVMFrame(_calleeGas, true) - success := staticcall(EVM_GAS_STIPEND(), _callee, _inputOffset, _inputLen, 0, 0) - - _gasLeft := _saveReturndataAfterEVMCall(_outputOffset, _outputLen) + _pushEVMFrame(gasToPass, true) + success := staticcall(EVM_GAS_STIPEND(), addr, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } @@ -1251,7 +1207,7 @@ function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { - revertWithGas(evmGasLeft) + revertWithGas(evmGasLeft) // TODO review } let value, offset, size diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 4fe751cba..7c6cedb7b 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -1383,28 +1383,28 @@ for { } true { } { 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) + switch isStatic + case 0 { + evmGasLeft, sp := performCall(sp, evmGasLeft) + } + default { + evmGasLeft, sp := performStaticCall(sp, evmGasLeft) + } + ip := add(ip, 1) } case 0xF3 { // OP_RETURN - let offset,size + 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))) + checkOverflow(offset, size, evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) - checkMemOverflowByOffset(add(offset,size), evmGasLeft) + checkMemOverflowByOffset(add(offset, size), evmGasLeft) returnLen := size @@ -1413,12 +1413,7 @@ for { } true { } { break } case 0xF4 { // OP_DELEGATECALL - evmGasLeft := chargeGas(evmGasLeft, 100) - - let gasUsed - sp, isStatic, gasUsed := delegateCall(sp, isStatic, evmGasLeft) - - evmGasLeft := chargeGas(evmGasLeft, gasUsed) + evmGasLeft, sp := performDelegateCall(sp, evmGasLeft, isStatic) ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 @@ -1430,11 +1425,7 @@ for { } true { } { ip := add(ip, 1) } case 0xFA { // OP_STATICCALL - evmGasLeft := chargeGas(evmGasLeft, 100) - - let gasUsed - gasUsed, sp := performStaticCall(sp,evmGasLeft) - evmGasLeft := chargeGas(evmGasLeft,gasUsed) + evmGasLeft, sp := performStaticCall(sp, evmGasLeft) ip := add(ip, 1) } case 0xFD { // OP_REVERT From 31465df18b212c420c288bf8c05af7b47046a369 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 22 Oct 2024 12:52:45 +0200 Subject: [PATCH 082/183] feat(EVM): Compiler based optimizations (#959) Signed-off-by: Vladimir Radosavljevic Co-authored-by: Vladimir Radosavljevic <129192835+vladimirradosavljevic@users.noreply.github.com> --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 2090 +++++++++++------ .../contracts/EvmEmulator.yul.llvm.options | 2 +- .../EvmEmulatorFunctions.template.yul | 176 +- .../evm-emulator/EvmEmulatorLoop.template.yul | 869 ++++--- 5 files changed, 1989 insertions(+), 1152 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 697ec4375..86ff1c676 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000da9de9056e6d87615b5f76bf4602c78f34b763452612dd5d0af6cd88f1b", - "sourceCodeHash": "0x2c951c86f5704857f1457b609a5985458dba815c8a0f1f8f0d8cf8108dde60b6" + "bytecodeHash": "0x01000d5550ffee2b5db585660d0c1a8c4511192658932adef00c322cd518bd29", + "sourceCodeHash": "0x414eb35f4032b71e34964e8b6e28db3bdc2b3e2b5801893dfb5c7365949483c6" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index beaaff9f5..86e6a3a3a 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -77,7 +77,7 @@ object "EvmEmulator" { } function STACK_OFFSET() -> offset { - offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 32) + offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } function BYTECODE_OFFSET() -> offset { @@ -112,23 +112,8 @@ object "EvmEmulator" { 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() + function $llvm_NoInline_llvm$_revert() { + revert(0, 0) } // It is the responsibility of the caller to ensure that ip >= BYTECODE_OFFSET + 32 @@ -147,71 +132,62 @@ object "EvmEmulator" { value := shr(mul(8,sub(32,length)),mload(start)) } - function dupStackItem(sp, evmGas, position) -> newSp, evmGasLeft { + function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) let tempSp := sub(sp, mul(0x20, sub(position, 1))) - if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + if lt(tempSp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let dup := mload(tempSp) - + mstore(sp, oldStackHead) + stackHead := mload(tempSp) newSp := add(sp, 0x20) - mstore(newSp, dup) } - function swapStackItem(sp, evmGas, position) -> evmGasLeft { + function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { 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()) { + if lt(tempSp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - - let s2 := mload(sp) - let s1 := mload(tempSp) - - mstore(sp, s1) - mstore(tempSp, s2) + stackHead := mload(tempSp) + mstore(tempSp, oldStackHead) } - function popStackItem(sp, evmGasLeft) -> a, newSp { + function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { // We can not return any error here, because it would break compatibility if lt(sp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - a := mload(sp) + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } - function pushStackItem(sp, item, evmGasLeft) -> newSp { - if or(gt(sp, BYTECODE_OFFSET()), eq(sp, BYTECODE_OFFSET())) { + function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { + if iszero(lt(sp, BYTECODE_OFFSET())) { revertWithGas(evmGasLeft) } + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } - function popStackItemWithoutCheck(sp) -> a, newSp { - a := mload(sp) + function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } - function pushStackItemWithoutCheck(sp, item) -> newSp { + function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } function popStackCheck(sp, evmGasLeft, numInputs) { @@ -855,17 +831,16 @@ object "EvmEmulator" { } } - function performCall(oldSp, evmGasLeft) -> newGasLeft, sp { + function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { 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) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -929,19 +904,18 @@ object "EvmEmulator" { } newGasLeft := chargeGas(evmGasLeft, gasUsed) - sp := pushStackItem(sp, success, newGasLeft) + stackHead := success } - function performStaticCall(oldSp, evmGasLeft) -> newEvmGasLeft, sp { + function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { 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) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -985,20 +959,21 @@ object "EvmEmulator" { gasUsed := precompileCost } - newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) - sp := pushStackItem(sp, success, newEvmGasLeft) + newGasLeft := chargeGas(evmGasLeft, gasUsed) + + stackHead := success } - function performDelegateCall(oldSp, evmGasLeft, isStatic) -> newEvmGasLeft, sp { + + function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEvmGasLeft, sp, stackHead { let addr, gasToPass, 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) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -1042,7 +1017,7 @@ object "EvmEmulator" { newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) - sp := pushStackItem(sp, success, newEvmGasLeft) + stackHead := success } function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { @@ -1111,7 +1086,7 @@ object "EvmEmulator" { gasLeft := mload(0) } - function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt) -> result, evmGasLeft, addr { + function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { _eraseReturndataPointer() let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) @@ -1123,10 +1098,10 @@ object "EvmEmulator" { 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))) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) _pushEVMFrame(gasForTheCall, false) @@ -1174,13 +1149,13 @@ object "EvmEmulator" { let back // skipping check since we pushed exactly 4 items earlier - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x20), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x40), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x60), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x80), back) } @@ -1223,15 +1198,15 @@ object "EvmEmulator" { } } - function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { + function performExtCodeCopy(evmGas,oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { 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) + addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost // minimum_word_size = (size + 31) / 32 @@ -1253,7 +1228,7 @@ object "EvmEmulator" { } } - function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { + function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -1263,9 +1238,8 @@ object "EvmEmulator" { let value, offset, size popStackCheck(oldSp, evmGasLeft, 3) - value, sp := popStackItemWithoutCheck(oldSp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1289,14 +1263,14 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) let result, addr - result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0) + result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { stackHead := 0 } + default { stackHead := addr } } - function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr{ + function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp, result, addr, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -1306,10 +1280,10 @@ object "EvmEmulator" { 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) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1332,7 +1306,7 @@ object "EvmEmulator" { shr(2, add(size, 31)) )) - result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt) + result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt, stackHead) } @@ -1351,6 +1325,7 @@ object "EvmEmulator" { // actual yul/evm instruction. let ip := add(BYTECODE_OFFSET(), 32) let opcode + let stackHead let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) @@ -1364,85 +1339,70 @@ object "EvmEmulator" { case 0x01 { // OP_ADD evmGasLeft := chargeGas(evmGasLeft, 3) - let a, b - popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := add(a, stackHead) - 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)) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mul(a, stackHead) 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) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := sub(a, stackHead) - 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) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := div(a, stackHead) - 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) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := sdiv(a, stackHead) - sp := pushStackItemWithoutCheck(sp, sdiv(a, b)) ip := add(ip, 1) } case 0x06 { // OP_MOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b - + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, mod(a, b)) ip := add(ip, 1) } case 0x07 { // OP_SMOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b - + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := smod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, smod(a, b)) ip := add(ip, 1) } case 0x08 { // OP_ADDMOD @@ -1451,11 +1411,10 @@ object "EvmEmulator" { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) + stackHead := addmod(a, b, N) - sp := pushStackItemWithoutCheck(sp, addmod(a, b, N)) ip := add(ip, 1) } case 0x09 { // OP_MULMOD @@ -1464,11 +1423,10 @@ object "EvmEmulator" { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItem(sp, mulmod(a, b, N), evmGasLeft) + stackHead := mulmod(a, b, N) ip := add(ip, 1) } case 0x0A { // OP_EXP @@ -1477,10 +1435,9 @@ object "EvmEmulator" { let a, exponent popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - exponent, sp := popStackItemWithoutCheck(sp) + a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, exp(a, exponent)) + stackHead := exp(a, exponent) let to_charge := 0 for {} gt(exponent,0) {} { // while exponent > 0 @@ -1496,10 +1453,9 @@ object "EvmEmulator" { let b, x popStackCheck(sp, evmGasLeft, 2) - b, sp := popStackItemWithoutCheck(sp) - x, sp := popStackItemWithoutCheck(sp) + b, sp, x := popStackItemWithoutCheck(sp, stackHead) + stackHead := signextend(b, x) - sp := pushStackItemWithoutCheck(sp, signextend(b, x)) ip := add(ip, 1) } case 0x10 { // OP_LT @@ -1508,10 +1464,9 @@ object "EvmEmulator" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := lt(a, b) - sp := pushStackItemWithoutCheck(sp, lt(a, b)) ip := add(ip, 1) } case 0x11 { // OP_GT @@ -1520,10 +1475,9 @@ object "EvmEmulator" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead:= gt(a, b) - sp := pushStackItemWithoutCheck(sp, gt(a, b)) ip := add(ip, 1) } case 0x12 { // OP_SLT @@ -1532,140 +1486,120 @@ object "EvmEmulator" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := slt(a, b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := sgt(a, b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := eq(a, b) - 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) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + stackHead := iszero(stackHead) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := and(a,b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := or(a,b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := xor(a, b) - sp := pushStackItemWithoutCheck(sp, xor(a, b)) ip := add(ip, 1) } case 0x19 { // OP_NOT evmGasLeft := chargeGas(evmGasLeft, 3) - let a + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - popStackCheck(sp, evmGasLeft, 1) - a, sp := popStackItemWithoutCheck(sp) + stackHead := not(stackHead) - 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) + i, sp, x := popStackItemWithoutCheck(sp, stackHead) + stackHead := byte(i, x) - 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) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) + stackHead := shl(shift, value) - 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) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) + stackHead := shr(shift, value) - 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) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) + stackHead := sar(shift, value) - sp := pushStackItemWithoutCheck(sp, sar(shift, value)) ip := add(ip, 1) } case 0x20 { // OP_KECCAK256 @@ -1674,8 +1608,7 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1688,63 +1621,66 @@ object "EvmEmulator" { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - sp := pushStackItem(sp, keccak, evmGasLeft) + stackHead := keccak ip := add(ip, 1) } case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, address(), evmGasLeft) + sp, stackHead := pushStackItem(sp, address(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x31 { // OP_BALANCE evmGasLeft := chargeGas(evmGasLeft, 100) - let addr + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - addr, sp := popStackItem(sp, evmGasLeft) + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, balance(addr)) + stackHead := balance(addr) + ip := add(ip, 1) } case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, origin(), evmGasLeft) + sp, stackHead := pushStackItem(sp, origin(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, caller(), evmGasLeft) + sp, stackHead := pushStackItem(sp, caller(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x34 { // OP_CALLVALUE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, callvalue(), evmGasLeft) + sp, stackHead := pushStackItem(sp, callvalue(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) + + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - let i - - popStackCheck(sp, evmGasLeft, 1) - i, sp := popStackItemWithoutCheck(sp) + stackHead := calldataload(stackHead) - sp := pushStackItemWithoutCheck(sp, calldataload(i)) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, calldatasize(), evmGasLeft) + sp, stackHead := pushStackItem(sp, calldatasize(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -1753,9 +1689,9 @@ object "EvmEmulator" { let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(destOffset, size, evmGasLeft) checkMemOverflowByOffset(add(destOffset,size), evmGasLeft) @@ -1773,7 +1709,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 2) let bytecodeLen := mload(BYTECODE_OFFSET()) - sp := pushStackItem(sp, bytecodeLen, evmGasLeft) + sp, stackHead := pushStackItem(sp, bytecodeLen, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x39 { // OP_CODECOPY @@ -1783,9 +1719,9 @@ object "EvmEmulator" { let dst, offset, len popStackCheck(sp, evmGasLeft, 3) - dst, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dst, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -1809,14 +1745,16 @@ object "EvmEmulator" { case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gasprice(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gasprice(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -1824,19 +1762,20 @@ object "EvmEmulator" { } switch _isEVM(addr) - case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } - default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } + case 0 { stackHead := extcodesize(addr) } + default { stackHead := _fetchDeployedCodeLen(addr) } + ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY - evmGasLeft, sp := performExtCodeCopy(evmGasLeft, sp) + evmGasLeft, sp, stackHead := performExtCodeCopy(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) - sp := pushStackItem(sp, rdz, evmGasLeft) + sp, stackHead := pushStackItem(sp, rdz, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3E { // OP_RETURNDATACOPY @@ -1844,9 +1783,9 @@ object "EvmEmulator" { let dest, offset, len popStackCheck(sp, evmGasLeft, 3) - dest, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,len, evmGasLeft) if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { @@ -1865,8 +1804,11 @@ object "EvmEmulator" { case 0x3F { // OP_EXTCODEHASH evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -1875,59 +1817,60 @@ object "EvmEmulator" { ip := add(ip, 1) if iszero(addr) { - sp := pushStackItemWithoutCheck(sp, 0) + stackHead := 0 continue } - sp := pushStackItemWithoutCheck(sp, extcodehash(addr)) + stackHead := extcodehash(addr) } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) - let blockNumber - popStackCheck(sp, evmGasLeft, 1) - blockNumber, sp := popStackItemWithoutCheck(sp) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + stackHead := blockhash(stackHead) - sp := pushStackItemWithoutCheck(sp, blockhash(blockNumber)) ip := add(ip, 1) } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, coinbase(), evmGasLeft) + sp, stackHead := pushStackItem(sp, coinbase(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, timestamp(), evmGasLeft) + sp, stackHead := pushStackItem(sp, timestamp(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, number(), evmGasLeft) + sp, stackHead := pushStackItem(sp, number(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, prevrandao(), evmGasLeft) + sp, stackHead := pushStackItem(sp, prevrandao(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gaslimit(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gaslimit(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, chainid(), evmGasLeft) + sp, stackHead := pushStackItem(sp, chainid(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE evmGasLeft := chargeGas(evmGasLeft, 5) - sp := pushStackItem(sp, selfbalance(), evmGasLeft) + sp, stackHead := pushStackItem(sp, selfbalance(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, basefee(), evmGasLeft) + sp, stackHead := pushStackItem(sp, basefee(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP @@ -1935,22 +1878,24 @@ object "EvmEmulator" { let _y - _y, sp := popStackItem(sp, evmGasLeft) + _y, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x51 { // OP_MLOAD evmGasLeft := chargeGas(evmGasLeft, 3) - let offset + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - offset, sp := popStackItem(sp, evmGasLeft) + let offset := stackHead 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) + stackHead := mload(add(MEM_OFFSET_INNER(), offset)) + ip := add(ip, 1) } case 0x52 { // OP_MSTORE @@ -1959,8 +1904,8 @@ object "EvmEmulator" { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) @@ -1975,8 +1920,8 @@ object "EvmEmulator" { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 1)) @@ -1991,7 +1936,10 @@ object "EvmEmulator" { let key, value, isWarm - key, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + key := stackHead let wasWarm := isSlotWarm(key) @@ -2005,7 +1953,7 @@ object "EvmEmulator" { let _wasW, _orgV := warmSlot(key, value) } - sp := pushStackItemWithoutCheck(sp,value) + stackHead := value ip := add(ip, 1) } case 0x55 { // OP_SSTORE @@ -2018,8 +1966,8 @@ object "EvmEmulator" { let key, value, gasSpent popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) ip := add(ip, 1) { @@ -2056,7 +2004,7 @@ object "EvmEmulator" { let counter - counter, sp := popStackItem(sp, evmGasLeft) + counter, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) @@ -2076,8 +2024,8 @@ object "EvmEmulator" { let counter, b popStackCheck(sp, evmGasLeft, 2) - counter, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + counter, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) if iszero(b) { ip := add(ip, 1) @@ -2101,7 +2049,7 @@ object "EvmEmulator" { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft, stackHead) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft,2) @@ -2110,13 +2058,13 @@ object "EvmEmulator" { size := mload(MEM_OFFSET()) size := shl(5,size) - sp := pushStackItem(sp,size, evmGasLeft) + sp, stackHead := pushStackItem(sp,size, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5A { // OP_GAS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, evmGasLeft, evmGasLeft) + sp, stackHead := pushStackItem(sp, evmGasLeft, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5B { // OP_JUMPDEST @@ -2126,11 +2074,11 @@ object "EvmEmulator" { case 0x5C { // OP_TLOAD evmGasLeft := chargeGas(evmGasLeft, 100) - let key - popStackCheck(sp, evmGasLeft, 1) - key, sp := popStackItemWithoutCheck(sp) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - sp := pushStackItemWithoutCheck(sp, tload(key)) + stackHead := tload(stackHead) ip := add(ip, 1) } case 0x5D { // OP_TSTORE @@ -2142,8 +2090,8 @@ object "EvmEmulator" { let key, value popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) tstore(key, value) ip := add(ip, 1) @@ -2151,9 +2099,9 @@ object "EvmEmulator" { case 0x5E { // OP_MCOPY let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkOverflow(destOffset, size, evmGasLeft) @@ -2171,7 +2119,7 @@ object "EvmEmulator" { let value := 0 - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x60 { // OP_PUSH1 @@ -2180,7 +2128,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,1) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x61 { // OP_PUSH2 @@ -2189,7 +2137,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,2) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 2) } case 0x62 { // OP_PUSH3 @@ -2198,7 +2146,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,3) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 3) } case 0x63 { // OP_PUSH4 @@ -2207,7 +2155,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,4) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 4) } case 0x64 { // OP_PUSH5 @@ -2216,7 +2164,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,5) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 5) } case 0x65 { // OP_PUSH6 @@ -2225,7 +2173,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,6) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 6) } case 0x66 { // OP_PUSH7 @@ -2234,7 +2182,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,7) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 7) } case 0x67 { // OP_PUSH8 @@ -2243,7 +2191,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,8) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 8) } case 0x68 { // OP_PUSH9 @@ -2252,7 +2200,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,9) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 9) } case 0x69 { // OP_PUSH10 @@ -2261,7 +2209,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,10) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 10) } case 0x6A { // OP_PUSH11 @@ -2270,7 +2218,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,11) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 11) } case 0x6B { // OP_PUSH12 @@ -2279,7 +2227,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,12) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 12) } case 0x6C { // OP_PUSH13 @@ -2288,7 +2236,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,13) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 13) } case 0x6D { // OP_PUSH14 @@ -2297,7 +2245,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,14) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 14) } case 0x6E { // OP_PUSH15 @@ -2306,7 +2254,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,15) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 15) } case 0x6F { // OP_PUSH16 @@ -2315,7 +2263,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,16) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 16) } case 0x70 { // OP_PUSH17 @@ -2324,7 +2272,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,17) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 17) } case 0x71 { // OP_PUSH18 @@ -2333,7 +2281,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,18) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 18) } case 0x72 { // OP_PUSH19 @@ -2342,7 +2290,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,19) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 19) } case 0x73 { // OP_PUSH20 @@ -2351,7 +2299,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,20) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 20) } case 0x74 { // OP_PUSH21 @@ -2360,7 +2308,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,21) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 21) } case 0x75 { // OP_PUSH22 @@ -2369,7 +2317,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,22) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 22) } case 0x76 { // OP_PUSH23 @@ -2378,7 +2326,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,23) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 23) } case 0x77 { // OP_PUSH24 @@ -2387,7 +2335,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,24) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 24) } case 0x78 { // OP_PUSH25 @@ -2396,7 +2344,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,25) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 25) } case 0x79 { // OP_PUSH26 @@ -2405,7 +2353,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,26) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 26) } case 0x7A { // OP_PUSH27 @@ -2414,7 +2362,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,27) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 27) } case 0x7B { // OP_PUSH28 @@ -2423,7 +2371,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,28) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 28) } case 0x7C { // OP_PUSH29 @@ -2432,7 +2380,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,29) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 29) } case 0x7D { // OP_PUSH30 @@ -2441,7 +2389,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,30) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 30) } case 0x7E { // OP_PUSH31 @@ -2450,7 +2398,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,31) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 31) } case 0x7F { // OP_PUSH32 @@ -2459,135 +2407,136 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,32) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 32) } case 0x80 { // OP_DUP1 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 1) + evmGasLeft := chargeGas(evmGasLeft, 3) + sp, stackHead := pushStackItem(sp, stackHead, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 2) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x82 { // OP_DUP3 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 3) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x83 { // OP_DUP4 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 4) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x84 { // OP_DUP5 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 5) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x85 { // OP_DUP6 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 6) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x86 { // OP_DUP7 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 7) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x87 { // OP_DUP8 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 8) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x88 { // OP_DUP9 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 9) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x89 { // OP_DUP10 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 10) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x8A { // OP_DUP11 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 11) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x8B { // OP_DUP12 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 12) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x8C { // OP_DUP13 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 13) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x8D { // OP_DUP14 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 14) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x8E { // OP_DUP15 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 15) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x8F { // OP_DUP16 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 16) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0x90 { // OP_SWAP1 - evmGasLeft := swapStackItem(sp, evmGasLeft, 1) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 1, stackHead) ip := add(ip, 1) } case 0x91 { // OP_SWAP2 - evmGasLeft := swapStackItem(sp, evmGasLeft, 2) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x92 { // OP_SWAP3 - evmGasLeft := swapStackItem(sp, evmGasLeft, 3) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x93 { // OP_SWAP4 - evmGasLeft := swapStackItem(sp, evmGasLeft, 4) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x94 { // OP_SWAP5 - evmGasLeft := swapStackItem(sp, evmGasLeft, 5) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x95 { // OP_SWAP6 - evmGasLeft := swapStackItem(sp, evmGasLeft, 6) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x96 { // OP_SWAP7 - evmGasLeft := swapStackItem(sp, evmGasLeft, 7) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x97 { // OP_SWAP8 - evmGasLeft := swapStackItem(sp, evmGasLeft, 8) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x98 { // OP_SWAP9 - evmGasLeft := swapStackItem(sp, evmGasLeft, 9) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x99 { // OP_SWAP10 - evmGasLeft := swapStackItem(sp, evmGasLeft, 10) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x9A { // OP_SWAP11 - evmGasLeft := swapStackItem(sp, evmGasLeft, 11) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x9B { // OP_SWAP12 - evmGasLeft := swapStackItem(sp, evmGasLeft, 12) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x9C { // OP_SWAP13 - evmGasLeft := swapStackItem(sp, evmGasLeft, 13) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x9D { // OP_SWAP14 - evmGasLeft := swapStackItem(sp, evmGasLeft, 14) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x9E { // OP_SWAP15 - evmGasLeft := swapStackItem(sp, evmGasLeft, 15) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x9F { // OP_SWAP16 - evmGasLeft := swapStackItem(sp, evmGasLeft, 16) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0xA0 { // OP_LOG0 @@ -2599,8 +2548,8 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2621,8 +2570,8 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 3) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2634,7 +2583,7 @@ object "EvmEmulator" { { let topic1 - topic1, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log1(add(offset, MEM_OFFSET_INNER()), size, topic1) } ip := add(ip, 1) @@ -2647,8 +2596,8 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 4) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2660,8 +2609,8 @@ object "EvmEmulator" { { let topic1, topic2 - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) } ip := add(ip, 1) @@ -2675,8 +2624,8 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 5) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2688,9 +2637,9 @@ object "EvmEmulator" { { let topic1, topic2, topic3 - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) } ip := add(ip, 1) @@ -2704,8 +2653,8 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 6) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2717,36 +2666,35 @@ object "EvmEmulator" { { let topic1, topic2, topic3, topic4 - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) - topic4, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) 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) + evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, isStatic, stackHead) ip := add(ip, 1) } case 0xF1 { // OP_CALL // A function was implemented in order to avoid stack depth errors. switch isStatic case 0 { - evmGasLeft, sp := performCall(sp, evmGasLeft) + evmGasLeft, sp, stackHead := performCall(sp, evmGasLeft, stackHead) } default { - evmGasLeft, sp := performStaticCall(sp, evmGasLeft) + evmGasLeft, sp, stackHead := performStaticCall(sp, evmGasLeft, stackHead) } - ip := add(ip, 1) } case 0xF3 { // OP_RETURN let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) @@ -2760,27 +2708,27 @@ object "EvmEmulator" { break } case 0xF4 { // OP_DELEGATECALL - evmGasLeft, sp := performDelegateCall(sp, evmGasLeft, isStatic) + evmGasLeft, sp, stackHead := performDelegateCall(sp, evmGasLeft, isStatic, stackHead) ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 let result, addr - evmGasLeft, sp, result, addr := performCreate2(evmGasLeft, sp, isStatic) + evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { sp, stackHead := pushStackItem(sp, 0, evmGasLeft, stackHead) } + default { sp, stackHead := pushStackItem(sp, addr, evmGasLeft, stackHead) } ip := add(ip, 1) } case 0xFA { // OP_STATICCALL - evmGasLeft, sp := performStaticCall(sp, evmGasLeft) + evmGasLeft, sp, stackHead := performStaticCall(sp,evmGasLeft, stackHead) ip := add(ip, 1) } case 0xFD { // OP_REVERT let offset,size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -2798,10 +2746,341 @@ object "EvmEmulator" { revertWithGas(evmGasLeft) } + case 0x0C { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x0D { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x0E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x0F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x1E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x1F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x21 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x22 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x23 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x24 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x25 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x26 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x27 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x28 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x29 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2A { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2B { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2C { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2D { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x49 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4A { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4B { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4C { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4D { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xED { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xFB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xFC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xFF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } default { - printString("INVALID OPCODE") - printHex(opcode) - revert(0, 0) + $llvm_NoInline_llvm$_revert() } } @@ -2868,7 +3147,7 @@ object "EvmEmulator" { } function STACK_OFFSET() -> offset { - offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 32) + offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } function BYTECODE_OFFSET() -> offset { @@ -2903,23 +3182,8 @@ object "EvmEmulator" { 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() + function $llvm_NoInline_llvm$_revert() { + revert(0, 0) } // It is the responsibility of the caller to ensure that ip >= BYTECODE_OFFSET + 32 @@ -2938,71 +3202,62 @@ object "EvmEmulator" { value := shr(mul(8,sub(32,length)),mload(start)) } - function dupStackItem(sp, evmGas, position) -> newSp, evmGasLeft { + function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { 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()) { + if lt(tempSp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - let dup := mload(tempSp) - + mstore(sp, oldStackHead) + stackHead := mload(tempSp) newSp := add(sp, 0x20) - mstore(newSp, dup) } - function swapStackItem(sp, evmGas, position) -> evmGasLeft { + function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { 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()) { + if lt(tempSp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - - let s2 := mload(sp) - let s1 := mload(tempSp) - - mstore(sp, s1) - mstore(tempSp, s2) + stackHead := mload(tempSp) + mstore(tempSp, oldStackHead) } - function popStackItem(sp, evmGasLeft) -> a, newSp { + function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { // We can not return any error here, because it would break compatibility if lt(sp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - a := mload(sp) + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } - function pushStackItem(sp, item, evmGasLeft) -> newSp { - if or(gt(sp, BYTECODE_OFFSET()), eq(sp, BYTECODE_OFFSET())) { + function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { + if iszero(lt(sp, BYTECODE_OFFSET())) { revertWithGas(evmGasLeft) } + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } - function popStackItemWithoutCheck(sp) -> a, newSp { - a := mload(sp) + function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } - function pushStackItemWithoutCheck(sp, item) -> newSp { + function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } function popStackCheck(sp, evmGasLeft, numInputs) { @@ -3646,17 +3901,16 @@ object "EvmEmulator" { } } - function performCall(oldSp, evmGasLeft) -> newGasLeft, sp { + function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { 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) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -3720,19 +3974,18 @@ object "EvmEmulator" { } newGasLeft := chargeGas(evmGasLeft, gasUsed) - sp := pushStackItem(sp, success, newGasLeft) + stackHead := success } - function performStaticCall(oldSp, evmGasLeft) -> newEvmGasLeft, sp { + function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { 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) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -3776,20 +4029,21 @@ object "EvmEmulator" { gasUsed := precompileCost } - newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) - sp := pushStackItem(sp, success, newEvmGasLeft) + newGasLeft := chargeGas(evmGasLeft, gasUsed) + + stackHead := success } - function performDelegateCall(oldSp, evmGasLeft, isStatic) -> newEvmGasLeft, sp { + + function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEvmGasLeft, sp, stackHead { let addr, gasToPass, 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) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -3833,7 +4087,7 @@ object "EvmEmulator" { newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) - sp := pushStackItem(sp, success, newEvmGasLeft) + stackHead := success } function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { @@ -3902,7 +4156,7 @@ object "EvmEmulator" { gasLeft := mload(0) } - function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt) -> result, evmGasLeft, addr { + function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { _eraseReturndataPointer() let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) @@ -3914,10 +4168,10 @@ object "EvmEmulator" { 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))) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) _pushEVMFrame(gasForTheCall, false) @@ -3965,13 +4219,13 @@ object "EvmEmulator" { let back // skipping check since we pushed exactly 4 items earlier - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x20), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x40), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x60), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x80), back) } @@ -4014,15 +4268,15 @@ object "EvmEmulator" { } } - function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { + function performExtCodeCopy(evmGas,oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { 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) + addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost // minimum_word_size = (size + 31) / 32 @@ -4044,7 +4298,7 @@ object "EvmEmulator" { } } - function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { + function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -4054,9 +4308,8 @@ object "EvmEmulator" { let value, offset, size popStackCheck(oldSp, evmGasLeft, 3) - value, sp := popStackItemWithoutCheck(oldSp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -4080,14 +4333,14 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) let result, addr - result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0) + result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { stackHead := 0 } + default { stackHead := addr } } - function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr{ + function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp, result, addr, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -4097,10 +4350,10 @@ object "EvmEmulator" { 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) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -4123,7 +4376,7 @@ object "EvmEmulator" { shr(2, add(size, 31)) )) - result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt) + result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt, stackHead) } @@ -4142,6 +4395,7 @@ object "EvmEmulator" { // actual yul/evm instruction. let ip := add(BYTECODE_OFFSET(), 32) let opcode + let stackHead let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) @@ -4155,85 +4409,70 @@ object "EvmEmulator" { case 0x01 { // OP_ADD evmGasLeft := chargeGas(evmGasLeft, 3) - let a, b - popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := add(a, stackHead) - 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)) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mul(a, stackHead) 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) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := sub(a, stackHead) - 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) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := div(a, stackHead) - 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) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := sdiv(a, stackHead) - sp := pushStackItemWithoutCheck(sp, sdiv(a, b)) ip := add(ip, 1) } case 0x06 { // OP_MOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b - + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, mod(a, b)) ip := add(ip, 1) } case 0x07 { // OP_SMOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b - + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := smod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, smod(a, b)) ip := add(ip, 1) } case 0x08 { // OP_ADDMOD @@ -4242,11 +4481,10 @@ object "EvmEmulator" { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) + stackHead := addmod(a, b, N) - sp := pushStackItemWithoutCheck(sp, addmod(a, b, N)) ip := add(ip, 1) } case 0x09 { // OP_MULMOD @@ -4255,11 +4493,10 @@ object "EvmEmulator" { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItem(sp, mulmod(a, b, N), evmGasLeft) + stackHead := mulmod(a, b, N) ip := add(ip, 1) } case 0x0A { // OP_EXP @@ -4268,10 +4505,9 @@ object "EvmEmulator" { let a, exponent popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - exponent, sp := popStackItemWithoutCheck(sp) + a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, exp(a, exponent)) + stackHead := exp(a, exponent) let to_charge := 0 for {} gt(exponent,0) {} { // while exponent > 0 @@ -4287,10 +4523,9 @@ object "EvmEmulator" { let b, x popStackCheck(sp, evmGasLeft, 2) - b, sp := popStackItemWithoutCheck(sp) - x, sp := popStackItemWithoutCheck(sp) + b, sp, x := popStackItemWithoutCheck(sp, stackHead) + stackHead := signextend(b, x) - sp := pushStackItemWithoutCheck(sp, signextend(b, x)) ip := add(ip, 1) } case 0x10 { // OP_LT @@ -4299,10 +4534,9 @@ object "EvmEmulator" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := lt(a, b) - sp := pushStackItemWithoutCheck(sp, lt(a, b)) ip := add(ip, 1) } case 0x11 { // OP_GT @@ -4311,10 +4545,9 @@ object "EvmEmulator" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead:= gt(a, b) - sp := pushStackItemWithoutCheck(sp, gt(a, b)) ip := add(ip, 1) } case 0x12 { // OP_SLT @@ -4323,140 +4556,120 @@ object "EvmEmulator" { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := slt(a, b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := sgt(a, b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := eq(a, b) - 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) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + stackHead := iszero(stackHead) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := and(a,b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := or(a,b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := xor(a, b) - sp := pushStackItemWithoutCheck(sp, xor(a, b)) ip := add(ip, 1) } case 0x19 { // OP_NOT evmGasLeft := chargeGas(evmGasLeft, 3) - let a + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - popStackCheck(sp, evmGasLeft, 1) - a, sp := popStackItemWithoutCheck(sp) + stackHead := not(stackHead) - 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) + i, sp, x := popStackItemWithoutCheck(sp, stackHead) + stackHead := byte(i, x) - 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) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) + stackHead := shl(shift, value) - 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) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) + stackHead := shr(shift, value) - 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) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) + stackHead := sar(shift, value) - sp := pushStackItemWithoutCheck(sp, sar(shift, value)) ip := add(ip, 1) } case 0x20 { // OP_KECCAK256 @@ -4465,8 +4678,7 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -4479,63 +4691,66 @@ object "EvmEmulator" { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - sp := pushStackItem(sp, keccak, evmGasLeft) + stackHead := keccak ip := add(ip, 1) } case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, address(), evmGasLeft) + sp, stackHead := pushStackItem(sp, address(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x31 { // OP_BALANCE evmGasLeft := chargeGas(evmGasLeft, 100) - let addr + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - addr, sp := popStackItem(sp, evmGasLeft) + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, balance(addr)) + stackHead := balance(addr) + ip := add(ip, 1) } case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, origin(), evmGasLeft) + sp, stackHead := pushStackItem(sp, origin(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, caller(), evmGasLeft) + sp, stackHead := pushStackItem(sp, caller(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x34 { // OP_CALLVALUE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, callvalue(), evmGasLeft) + sp, stackHead := pushStackItem(sp, callvalue(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) + + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - let i - - popStackCheck(sp, evmGasLeft, 1) - i, sp := popStackItemWithoutCheck(sp) + stackHead := calldataload(stackHead) - sp := pushStackItemWithoutCheck(sp, calldataload(i)) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, calldatasize(), evmGasLeft) + sp, stackHead := pushStackItem(sp, calldatasize(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -4544,9 +4759,9 @@ object "EvmEmulator" { let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(destOffset, size, evmGasLeft) checkMemOverflowByOffset(add(destOffset,size), evmGasLeft) @@ -4564,7 +4779,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 2) let bytecodeLen := mload(BYTECODE_OFFSET()) - sp := pushStackItem(sp, bytecodeLen, evmGasLeft) + sp, stackHead := pushStackItem(sp, bytecodeLen, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x39 { // OP_CODECOPY @@ -4574,9 +4789,9 @@ object "EvmEmulator" { let dst, offset, len popStackCheck(sp, evmGasLeft, 3) - dst, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dst, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -4600,14 +4815,16 @@ object "EvmEmulator" { case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gasprice(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gasprice(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -4615,19 +4832,20 @@ object "EvmEmulator" { } switch _isEVM(addr) - case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } - default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } + case 0 { stackHead := extcodesize(addr) } + default { stackHead := _fetchDeployedCodeLen(addr) } + ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY - evmGasLeft, sp := performExtCodeCopy(evmGasLeft, sp) + evmGasLeft, sp, stackHead := performExtCodeCopy(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) - sp := pushStackItem(sp, rdz, evmGasLeft) + sp, stackHead := pushStackItem(sp, rdz, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3E { // OP_RETURNDATACOPY @@ -4635,9 +4853,9 @@ object "EvmEmulator" { let dest, offset, len popStackCheck(sp, evmGasLeft, 3) - dest, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,len, evmGasLeft) if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { @@ -4656,8 +4874,11 @@ object "EvmEmulator" { case 0x3F { // OP_EXTCODEHASH evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -4666,59 +4887,60 @@ object "EvmEmulator" { ip := add(ip, 1) if iszero(addr) { - sp := pushStackItemWithoutCheck(sp, 0) + stackHead := 0 continue } - sp := pushStackItemWithoutCheck(sp, extcodehash(addr)) + stackHead := extcodehash(addr) } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) - let blockNumber - popStackCheck(sp, evmGasLeft, 1) - blockNumber, sp := popStackItemWithoutCheck(sp) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + stackHead := blockhash(stackHead) - sp := pushStackItemWithoutCheck(sp, blockhash(blockNumber)) ip := add(ip, 1) } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, coinbase(), evmGasLeft) + sp, stackHead := pushStackItem(sp, coinbase(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, timestamp(), evmGasLeft) + sp, stackHead := pushStackItem(sp, timestamp(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, number(), evmGasLeft) + sp, stackHead := pushStackItem(sp, number(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, prevrandao(), evmGasLeft) + sp, stackHead := pushStackItem(sp, prevrandao(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gaslimit(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gaslimit(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, chainid(), evmGasLeft) + sp, stackHead := pushStackItem(sp, chainid(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE evmGasLeft := chargeGas(evmGasLeft, 5) - sp := pushStackItem(sp, selfbalance(), evmGasLeft) + sp, stackHead := pushStackItem(sp, selfbalance(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, basefee(), evmGasLeft) + sp, stackHead := pushStackItem(sp, basefee(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP @@ -4726,22 +4948,24 @@ object "EvmEmulator" { let _y - _y, sp := popStackItem(sp, evmGasLeft) + _y, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x51 { // OP_MLOAD evmGasLeft := chargeGas(evmGasLeft, 3) - let offset + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - offset, sp := popStackItem(sp, evmGasLeft) + let offset := stackHead 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) + stackHead := mload(add(MEM_OFFSET_INNER(), offset)) + ip := add(ip, 1) } case 0x52 { // OP_MSTORE @@ -4750,8 +4974,8 @@ object "EvmEmulator" { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) @@ -4766,8 +4990,8 @@ object "EvmEmulator" { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 1)) @@ -4782,7 +5006,10 @@ object "EvmEmulator" { let key, value, isWarm - key, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + key := stackHead let wasWarm := isSlotWarm(key) @@ -4796,7 +5023,7 @@ object "EvmEmulator" { let _wasW, _orgV := warmSlot(key, value) } - sp := pushStackItemWithoutCheck(sp,value) + stackHead := value ip := add(ip, 1) } case 0x55 { // OP_SSTORE @@ -4809,8 +5036,8 @@ object "EvmEmulator" { let key, value, gasSpent popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) ip := add(ip, 1) { @@ -4847,7 +5074,7 @@ object "EvmEmulator" { let counter - counter, sp := popStackItem(sp, evmGasLeft) + counter, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) @@ -4867,8 +5094,8 @@ object "EvmEmulator" { let counter, b popStackCheck(sp, evmGasLeft, 2) - counter, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + counter, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) if iszero(b) { ip := add(ip, 1) @@ -4892,7 +5119,7 @@ object "EvmEmulator" { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft, stackHead) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft,2) @@ -4901,13 +5128,13 @@ object "EvmEmulator" { size := mload(MEM_OFFSET()) size := shl(5,size) - sp := pushStackItem(sp,size, evmGasLeft) + sp, stackHead := pushStackItem(sp,size, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5A { // OP_GAS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, evmGasLeft, evmGasLeft) + sp, stackHead := pushStackItem(sp, evmGasLeft, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5B { // OP_JUMPDEST @@ -4917,11 +5144,11 @@ object "EvmEmulator" { case 0x5C { // OP_TLOAD evmGasLeft := chargeGas(evmGasLeft, 100) - let key - popStackCheck(sp, evmGasLeft, 1) - key, sp := popStackItemWithoutCheck(sp) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - sp := pushStackItemWithoutCheck(sp, tload(key)) + stackHead := tload(stackHead) ip := add(ip, 1) } case 0x5D { // OP_TSTORE @@ -4933,8 +5160,8 @@ object "EvmEmulator" { let key, value popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) tstore(key, value) ip := add(ip, 1) @@ -4942,9 +5169,9 @@ object "EvmEmulator" { case 0x5E { // OP_MCOPY let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkOverflow(destOffset, size, evmGasLeft) @@ -4962,7 +5189,7 @@ object "EvmEmulator" { let value := 0 - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x60 { // OP_PUSH1 @@ -4971,7 +5198,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,1) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x61 { // OP_PUSH2 @@ -4980,7 +5207,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,2) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 2) } case 0x62 { // OP_PUSH3 @@ -4989,7 +5216,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,3) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 3) } case 0x63 { // OP_PUSH4 @@ -4998,7 +5225,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,4) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 4) } case 0x64 { // OP_PUSH5 @@ -5007,7 +5234,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,5) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 5) } case 0x65 { // OP_PUSH6 @@ -5016,7 +5243,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,6) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 6) } case 0x66 { // OP_PUSH7 @@ -5025,7 +5252,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,7) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 7) } case 0x67 { // OP_PUSH8 @@ -5034,7 +5261,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,8) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 8) } case 0x68 { // OP_PUSH9 @@ -5043,7 +5270,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,9) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 9) } case 0x69 { // OP_PUSH10 @@ -5052,7 +5279,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,10) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 10) } case 0x6A { // OP_PUSH11 @@ -5061,7 +5288,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,11) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 11) } case 0x6B { // OP_PUSH12 @@ -5070,7 +5297,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,12) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 12) } case 0x6C { // OP_PUSH13 @@ -5079,7 +5306,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,13) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 13) } case 0x6D { // OP_PUSH14 @@ -5088,7 +5315,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,14) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 14) } case 0x6E { // OP_PUSH15 @@ -5097,7 +5324,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,15) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 15) } case 0x6F { // OP_PUSH16 @@ -5106,7 +5333,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,16) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 16) } case 0x70 { // OP_PUSH17 @@ -5115,7 +5342,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,17) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 17) } case 0x71 { // OP_PUSH18 @@ -5124,7 +5351,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,18) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 18) } case 0x72 { // OP_PUSH19 @@ -5133,7 +5360,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,19) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 19) } case 0x73 { // OP_PUSH20 @@ -5142,7 +5369,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,20) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 20) } case 0x74 { // OP_PUSH21 @@ -5151,7 +5378,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,21) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 21) } case 0x75 { // OP_PUSH22 @@ -5160,7 +5387,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,22) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 22) } case 0x76 { // OP_PUSH23 @@ -5169,7 +5396,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,23) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 23) } case 0x77 { // OP_PUSH24 @@ -5178,7 +5405,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,24) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 24) } case 0x78 { // OP_PUSH25 @@ -5187,7 +5414,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,25) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 25) } case 0x79 { // OP_PUSH26 @@ -5196,7 +5423,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,26) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 26) } case 0x7A { // OP_PUSH27 @@ -5205,7 +5432,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,27) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 27) } case 0x7B { // OP_PUSH28 @@ -5214,7 +5441,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,28) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 28) } case 0x7C { // OP_PUSH29 @@ -5223,7 +5450,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,29) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 29) } case 0x7D { // OP_PUSH30 @@ -5232,7 +5459,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,30) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 30) } case 0x7E { // OP_PUSH31 @@ -5241,7 +5468,7 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,31) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 31) } case 0x7F { // OP_PUSH32 @@ -5250,135 +5477,136 @@ object "EvmEmulator" { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,32) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 32) } case 0x80 { // OP_DUP1 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 1) + evmGasLeft := chargeGas(evmGasLeft, 3) + sp, stackHead := pushStackItem(sp, stackHead, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 2) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x82 { // OP_DUP3 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 3) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x83 { // OP_DUP4 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 4) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x84 { // OP_DUP5 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 5) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x85 { // OP_DUP6 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 6) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x86 { // OP_DUP7 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 7) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x87 { // OP_DUP8 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 8) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x88 { // OP_DUP9 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 9) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x89 { // OP_DUP10 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 10) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x8A { // OP_DUP11 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 11) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x8B { // OP_DUP12 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 12) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x8C { // OP_DUP13 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 13) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x8D { // OP_DUP14 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 14) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x8E { // OP_DUP15 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 15) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x8F { // OP_DUP16 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 16) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0x90 { // OP_SWAP1 - evmGasLeft := swapStackItem(sp, evmGasLeft, 1) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 1, stackHead) ip := add(ip, 1) } case 0x91 { // OP_SWAP2 - evmGasLeft := swapStackItem(sp, evmGasLeft, 2) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x92 { // OP_SWAP3 - evmGasLeft := swapStackItem(sp, evmGasLeft, 3) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x93 { // OP_SWAP4 - evmGasLeft := swapStackItem(sp, evmGasLeft, 4) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x94 { // OP_SWAP5 - evmGasLeft := swapStackItem(sp, evmGasLeft, 5) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x95 { // OP_SWAP6 - evmGasLeft := swapStackItem(sp, evmGasLeft, 6) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x96 { // OP_SWAP7 - evmGasLeft := swapStackItem(sp, evmGasLeft, 7) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x97 { // OP_SWAP8 - evmGasLeft := swapStackItem(sp, evmGasLeft, 8) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x98 { // OP_SWAP9 - evmGasLeft := swapStackItem(sp, evmGasLeft, 9) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x99 { // OP_SWAP10 - evmGasLeft := swapStackItem(sp, evmGasLeft, 10) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x9A { // OP_SWAP11 - evmGasLeft := swapStackItem(sp, evmGasLeft, 11) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x9B { // OP_SWAP12 - evmGasLeft := swapStackItem(sp, evmGasLeft, 12) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x9C { // OP_SWAP13 - evmGasLeft := swapStackItem(sp, evmGasLeft, 13) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x9D { // OP_SWAP14 - evmGasLeft := swapStackItem(sp, evmGasLeft, 14) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x9E { // OP_SWAP15 - evmGasLeft := swapStackItem(sp, evmGasLeft, 15) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x9F { // OP_SWAP16 - evmGasLeft := swapStackItem(sp, evmGasLeft, 16) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0xA0 { // OP_LOG0 @@ -5390,8 +5618,8 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5412,8 +5640,8 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 3) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5425,7 +5653,7 @@ object "EvmEmulator" { { let topic1 - topic1, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log1(add(offset, MEM_OFFSET_INNER()), size, topic1) } ip := add(ip, 1) @@ -5438,8 +5666,8 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 4) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5451,8 +5679,8 @@ object "EvmEmulator" { { let topic1, topic2 - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) } ip := add(ip, 1) @@ -5466,8 +5694,8 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 5) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5479,9 +5707,9 @@ object "EvmEmulator" { { let topic1, topic2, topic3 - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) } ip := add(ip, 1) @@ -5495,8 +5723,8 @@ object "EvmEmulator" { let offset, size popStackCheck(sp, evmGasLeft, 6) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5508,36 +5736,35 @@ object "EvmEmulator" { { let topic1, topic2, topic3, topic4 - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) - topic4, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) 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) + evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, isStatic, stackHead) ip := add(ip, 1) } case 0xF1 { // OP_CALL // A function was implemented in order to avoid stack depth errors. switch isStatic case 0 { - evmGasLeft, sp := performCall(sp, evmGasLeft) + evmGasLeft, sp, stackHead := performCall(sp, evmGasLeft, stackHead) } default { - evmGasLeft, sp := performStaticCall(sp, evmGasLeft) + evmGasLeft, sp, stackHead := performStaticCall(sp, evmGasLeft, stackHead) } - ip := add(ip, 1) } case 0xF3 { // OP_RETURN let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) @@ -5551,27 +5778,27 @@ object "EvmEmulator" { break } case 0xF4 { // OP_DELEGATECALL - evmGasLeft, sp := performDelegateCall(sp, evmGasLeft, isStatic) + evmGasLeft, sp, stackHead := performDelegateCall(sp, evmGasLeft, isStatic, stackHead) ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 let result, addr - evmGasLeft, sp, result, addr := performCreate2(evmGasLeft, sp, isStatic) + evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { sp, stackHead := pushStackItem(sp, 0, evmGasLeft, stackHead) } + default { sp, stackHead := pushStackItem(sp, addr, evmGasLeft, stackHead) } ip := add(ip, 1) } case 0xFA { // OP_STATICCALL - evmGasLeft, sp := performStaticCall(sp, evmGasLeft) + evmGasLeft, sp, stackHead := performStaticCall(sp,evmGasLeft, stackHead) ip := add(ip, 1) } case 0xFD { // OP_REVERT let offset,size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -5589,10 +5816,341 @@ object "EvmEmulator" { revertWithGas(evmGasLeft) } + case 0x0C { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x0D { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x0E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x0F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x1E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x1F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x21 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x22 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x23 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x24 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x25 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x26 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x27 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x28 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x29 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2A { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2B { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2C { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2D { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x49 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4A { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4B { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4C { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4D { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xED { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xFB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xFC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xFF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } default { - printString("INVALID OPCODE") - printHex(opcode) - revert(0, 0) + $llvm_NoInline_llvm$_revert() } } diff --git a/system-contracts/contracts/EvmEmulator.yul.llvm.options b/system-contracts/contracts/EvmEmulator.yul.llvm.options index 98f38d107..ea418b985 100644 --- a/system-contracts/contracts/EvmEmulator.yul.llvm.options +++ b/system-contracts/contracts/EvmEmulator.yul.llvm.options @@ -1 +1 @@ -'-eravm-jump-table-density-threshold=10 -tail-dup-size=4 -eravm-enable-split-loop-phi-live-ranges -tail-merge-only-bbs-without-succ' \ No newline at end of file +'-eravm-jump-table-density-threshold=10 -tail-dup-size=6 -eravm-enable-split-loop-phi-live-ranges -tail-merge-only-bbs-without-succ -join-globalcopies -disable-early-taildup' \ No newline at end of file diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 45fc86b04..810dbfa70 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -27,7 +27,7 @@ function LAST_RETURNDATA_SIZE_OFFSET() -> offset { } function STACK_OFFSET() -> offset { - offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 32) + offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } function BYTECODE_OFFSET() -> offset { @@ -62,23 +62,8 @@ 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() +function $llvm_NoInline_llvm$_revert() { + revert(0, 0) } // It is the responsibility of the caller to ensure that ip >= BYTECODE_OFFSET + 32 @@ -97,71 +82,62 @@ function readBytes(start, maxAcceptablePos,length) -> value { value := shr(mul(8,sub(32,length)),mload(start)) } -function dupStackItem(sp, evmGas, position) -> newSp, evmGasLeft { +function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) let tempSp := sub(sp, mul(0x20, sub(position, 1))) - if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + if lt(tempSp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let dup := mload(tempSp) - + mstore(sp, oldStackHead) + stackHead := mload(tempSp) newSp := add(sp, 0x20) - mstore(newSp, dup) } -function swapStackItem(sp, evmGas, position) -> evmGasLeft { +function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) let tempSp := sub(sp, mul(0x20, position)) - if or(gt(tempSp, BYTECODE_OFFSET()), eq(tempSp, BYTECODE_OFFSET())) { + if lt(tempSp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - - let s2 := mload(sp) - let s1 := mload(tempSp) - - mstore(sp, s1) - mstore(tempSp, s2) + stackHead := mload(tempSp) + mstore(tempSp, oldStackHead) } -function popStackItem(sp, evmGasLeft) -> a, newSp { +function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { // We can not return any error here, because it would break compatibility if lt(sp, STACK_OFFSET()) { revertWithGas(evmGasLeft) } - a := mload(sp) + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } -function pushStackItem(sp, item, evmGasLeft) -> newSp { - if or(gt(sp, BYTECODE_OFFSET()), eq(sp, BYTECODE_OFFSET())) { +function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { + if iszero(lt(sp, BYTECODE_OFFSET())) { revertWithGas(evmGasLeft) } + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } -function popStackItemWithoutCheck(sp) -> a, newSp { - a := mload(sp) +function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { + a := oldStackHead newSp := sub(sp, 0x20) + stackHead := mload(newSp) } -function pushStackItemWithoutCheck(sp, item) -> newSp { +function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { + mstore(sp, oldStackHead) + stackHead := item newSp := add(sp, 0x20) - mstore(newSp, item) } function popStackCheck(sp, evmGasLeft, numInputs) { @@ -805,17 +781,16 @@ function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> } } -function performCall(oldSp, evmGasLeft) -> newGasLeft, sp { +function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { 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) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -879,19 +854,18 @@ function performCall(oldSp, evmGasLeft) -> newGasLeft, sp { } newGasLeft := chargeGas(evmGasLeft, gasUsed) - sp := pushStackItem(sp, success, newGasLeft) + stackHead := success } -function performStaticCall(oldSp, evmGasLeft) -> newEvmGasLeft, sp { +function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { 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) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -935,20 +909,21 @@ function performStaticCall(oldSp, evmGasLeft) -> newEvmGasLeft, sp { gasUsed := precompileCost } - newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) - sp := pushStackItem(sp, success, newEvmGasLeft) + newGasLeft := chargeGas(evmGasLeft, gasUsed) + + stackHead := success } -function performDelegateCall(oldSp, evmGasLeft, isStatic) -> newEvmGasLeft, sp { + +function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEvmGasLeft, sp, stackHead { let addr, gasToPass, 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) + gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) @@ -992,7 +967,7 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic) -> newEvmGasLeft, sp { newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) - sp := pushStackItem(sp, success, newEvmGasLeft) + stackHead := success } function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { @@ -1061,7 +1036,7 @@ function _fetchConstructorReturnGas() -> gasLeft { gasLeft := mload(0) } -function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt) -> result, evmGasLeft, addr { +function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { _eraseReturndataPointer() let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) @@ -1073,10 +1048,10 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO 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))) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) _pushEVMFrame(gasForTheCall, false) @@ -1124,13 +1099,13 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO let back // skipping check since we pushed exactly 4 items earlier - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x20), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x40), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x60), back) - back, sp := popStackItemWithoutCheck(sp) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) mstore(sub(offset, 0x80), back) } @@ -1173,15 +1148,15 @@ function $llvm_AlwaysInline_llvm$_memsetToZero(dest,len) { } } -function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { +function performExtCodeCopy(evmGas,oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { 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) + addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost // minimum_word_size = (size + 31) / 32 @@ -1203,7 +1178,7 @@ function performExtCodeCopy(evmGas,oldSp) -> evmGasLeft, sp { } } -function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { +function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -1213,9 +1188,8 @@ function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { let value, offset, size popStackCheck(oldSp, evmGasLeft, 3) - value, sp := popStackItemWithoutCheck(oldSp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1239,14 +1213,14 @@ function performCreate(evmGas,oldSp,isStatic) -> evmGasLeft, sp { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) let result, addr - result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0) + result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { stackHead := 0 } + default { stackHead := addr } } -function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr{ +function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp, result, addr, stackHead { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { @@ -1256,10 +1230,10 @@ function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr 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) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1282,5 +1256,5 @@ function performCreate2(evmGas, oldSp, isStatic) -> evmGasLeft, sp, result, addr shr(2, add(size, 31)) )) - result, evmGasLeft, addr := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt) + result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt, stackHead) } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 7c6cedb7b..d20f73be4 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -4,6 +4,7 @@ let sp := sub(STACK_OFFSET(), 32) // actual yul/evm instruction. let ip := add(BYTECODE_OFFSET(), 32) let opcode +let stackHead let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) @@ -17,85 +18,70 @@ for { } true { } { case 0x01 { // OP_ADD evmGasLeft := chargeGas(evmGasLeft, 3) - let a, b - popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := add(a, stackHead) - 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)) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mul(a, stackHead) 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) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := sub(a, stackHead) - 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) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := div(a, stackHead) - 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) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := sdiv(a, stackHead) - sp := pushStackItemWithoutCheck(sp, sdiv(a, b)) ip := add(ip, 1) } case 0x06 { // OP_MOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b - + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := mod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, mod(a, b)) ip := add(ip, 1) } case 0x07 { // OP_SMOD evmGasLeft := chargeGas(evmGasLeft, 5) - let a, b - + let a popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := smod(a, stackHead) - sp := pushStackItemWithoutCheck(sp, smod(a, b)) ip := add(ip, 1) } case 0x08 { // OP_ADDMOD @@ -104,11 +90,10 @@ for { } true { } { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) + stackHead := addmod(a, b, N) - sp := pushStackItemWithoutCheck(sp, addmod(a, b, N)) ip := add(ip, 1) } case 0x09 { // OP_MULMOD @@ -117,11 +102,10 @@ for { } true { } { let a, b, N popStackCheck(sp, evmGasLeft, 3) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) - N, sp := popStackItemWithoutCheck(sp) + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, N := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItem(sp, mulmod(a, b, N), evmGasLeft) + stackHead := mulmod(a, b, N) ip := add(ip, 1) } case 0x0A { // OP_EXP @@ -130,10 +114,9 @@ for { } true { } { let a, exponent popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - exponent, sp := popStackItemWithoutCheck(sp) + a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) - sp := pushStackItemWithoutCheck(sp, exp(a, exponent)) + stackHead := exp(a, exponent) let to_charge := 0 for {} gt(exponent,0) {} { // while exponent > 0 @@ -149,10 +132,9 @@ for { } true { } { let b, x popStackCheck(sp, evmGasLeft, 2) - b, sp := popStackItemWithoutCheck(sp) - x, sp := popStackItemWithoutCheck(sp) + b, sp, x := popStackItemWithoutCheck(sp, stackHead) + stackHead := signextend(b, x) - sp := pushStackItemWithoutCheck(sp, signextend(b, x)) ip := add(ip, 1) } case 0x10 { // OP_LT @@ -161,10 +143,9 @@ for { } true { } { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := lt(a, b) - sp := pushStackItemWithoutCheck(sp, lt(a, b)) ip := add(ip, 1) } case 0x11 { // OP_GT @@ -173,10 +154,9 @@ for { } true { } { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead:= gt(a, b) - sp := pushStackItemWithoutCheck(sp, gt(a, b)) ip := add(ip, 1) } case 0x12 { // OP_SLT @@ -185,140 +165,120 @@ for { } true { } { let a, b popStackCheck(sp, evmGasLeft, 2) - a, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := slt(a, b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := sgt(a, b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := eq(a, b) - 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) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + stackHead := iszero(stackHead) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := and(a,b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := or(a,b) - 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) + a, sp, b := popStackItemWithoutCheck(sp, stackHead) + stackHead := xor(a, b) - sp := pushStackItemWithoutCheck(sp, xor(a, b)) ip := add(ip, 1) } case 0x19 { // OP_NOT evmGasLeft := chargeGas(evmGasLeft, 3) - let a + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - popStackCheck(sp, evmGasLeft, 1) - a, sp := popStackItemWithoutCheck(sp) + stackHead := not(stackHead) - 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) + i, sp, x := popStackItemWithoutCheck(sp, stackHead) + stackHead := byte(i, x) - 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) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) + stackHead := shl(shift, value) - 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) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) + stackHead := shr(shift, value) - 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) + shift, sp, value := popStackItemWithoutCheck(sp, stackHead) + stackHead := sar(shift, value) - sp := pushStackItemWithoutCheck(sp, sar(shift, value)) ip := add(ip, 1) } case 0x20 { // OP_KECCAK256 @@ -327,8 +287,7 @@ for { } true { } { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -341,63 +300,66 @@ for { } true { } { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - sp := pushStackItem(sp, keccak, evmGasLeft) + stackHead := keccak ip := add(ip, 1) } case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, address(), evmGasLeft) + sp, stackHead := pushStackItem(sp, address(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x31 { // OP_BALANCE evmGasLeft := chargeGas(evmGasLeft, 100) - let addr + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - addr, sp := popStackItem(sp, evmGasLeft) + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { evmGasLeft := chargeGas(evmGasLeft, 2500) } - sp := pushStackItemWithoutCheck(sp, balance(addr)) + stackHead := balance(addr) + ip := add(ip, 1) } case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, origin(), evmGasLeft) + sp, stackHead := pushStackItem(sp, origin(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, caller(), evmGasLeft) + sp, stackHead := pushStackItem(sp, caller(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x34 { // OP_CALLVALUE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, callvalue(), evmGasLeft) + sp, stackHead := pushStackItem(sp, callvalue(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) + + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - let i - - popStackCheck(sp, evmGasLeft, 1) - i, sp := popStackItemWithoutCheck(sp) + stackHead := calldataload(stackHead) - sp := pushStackItemWithoutCheck(sp, calldataload(i)) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, calldatasize(), evmGasLeft) + sp, stackHead := pushStackItem(sp, calldatasize(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -406,9 +368,9 @@ for { } true { } { let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(destOffset, size, evmGasLeft) checkMemOverflowByOffset(add(destOffset,size), evmGasLeft) @@ -426,7 +388,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 2) let bytecodeLen := mload(BYTECODE_OFFSET()) - sp := pushStackItem(sp, bytecodeLen, evmGasLeft) + sp, stackHead := pushStackItem(sp, bytecodeLen, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x39 { // OP_CODECOPY @@ -436,9 +398,9 @@ for { } true { } { let dst, offset, len popStackCheck(sp, evmGasLeft, 3) - dst, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dst, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -462,14 +424,16 @@ for { } true { } { case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gasprice(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gasprice(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -477,19 +441,20 @@ for { } true { } { } switch _isEVM(addr) - case 0 { sp := pushStackItemWithoutCheck(sp, extcodesize(addr)) } - default { sp := pushStackItemWithoutCheck(sp, _fetchDeployedCodeLen(addr)) } + case 0 { stackHead := extcodesize(addr) } + default { stackHead := _fetchDeployedCodeLen(addr) } + ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY - evmGasLeft, sp := performExtCodeCopy(evmGasLeft, sp) + evmGasLeft, sp, stackHead := performExtCodeCopy(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) - sp := pushStackItem(sp, rdz, evmGasLeft) + sp, stackHead := pushStackItem(sp, rdz, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x3E { // OP_RETURNDATACOPY @@ -497,9 +462,9 @@ for { } true { } { let dest, offset, len popStackCheck(sp, evmGasLeft, 3) - dest, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - len, sp := popStackItemWithoutCheck(sp) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,len, evmGasLeft) if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { @@ -518,8 +483,11 @@ for { } true { } { case 0x3F { // OP_EXTCODEHASH evmGasLeft := chargeGas(evmGasLeft, 100) - let addr - addr, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + let addr := stackHead addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -528,59 +496,60 @@ for { } true { } { ip := add(ip, 1) if iszero(addr) { - sp := pushStackItemWithoutCheck(sp, 0) + stackHead := 0 continue } - sp := pushStackItemWithoutCheck(sp, extcodehash(addr)) + stackHead := extcodehash(addr) } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) - let blockNumber - popStackCheck(sp, evmGasLeft, 1) - blockNumber, sp := popStackItemWithoutCheck(sp) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + + stackHead := blockhash(stackHead) - sp := pushStackItemWithoutCheck(sp, blockhash(blockNumber)) ip := add(ip, 1) } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, coinbase(), evmGasLeft) + sp, stackHead := pushStackItem(sp, coinbase(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, timestamp(), evmGasLeft) + sp, stackHead := pushStackItem(sp, timestamp(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, number(), evmGasLeft) + sp, stackHead := pushStackItem(sp, number(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, prevrandao(), evmGasLeft) + sp, stackHead := pushStackItem(sp, prevrandao(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, gaslimit(), evmGasLeft) + sp, stackHead := pushStackItem(sp, gaslimit(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, chainid(), evmGasLeft) + sp, stackHead := pushStackItem(sp, chainid(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE evmGasLeft := chargeGas(evmGasLeft, 5) - sp := pushStackItem(sp, selfbalance(), evmGasLeft) + sp, stackHead := pushStackItem(sp, selfbalance(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, basefee(), evmGasLeft) + sp, stackHead := pushStackItem(sp, basefee(), evmGasLeft, stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP @@ -588,22 +557,24 @@ for { } true { } { let _y - _y, sp := popStackItem(sp, evmGasLeft) + _y, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x51 { // OP_MLOAD evmGasLeft := chargeGas(evmGasLeft, 3) - let offset + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - offset, sp := popStackItem(sp, evmGasLeft) + let offset := stackHead 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) + stackHead := mload(add(MEM_OFFSET_INNER(), offset)) + ip := add(ip, 1) } case 0x52 { // OP_MSTORE @@ -612,8 +583,8 @@ for { } true { } { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 32)) @@ -628,8 +599,8 @@ for { } true { } { let offset, value popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemOverflowByOffset(offset, evmGasLeft) let expansionGas := expandMemory(add(offset, 1)) @@ -644,7 +615,10 @@ for { } true { } { let key, value, isWarm - key, sp := popStackItem(sp, evmGasLeft) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } + key := stackHead let wasWarm := isSlotWarm(key) @@ -658,7 +632,7 @@ for { } true { } { let _wasW, _orgV := warmSlot(key, value) } - sp := pushStackItemWithoutCheck(sp,value) + stackHead := value ip := add(ip, 1) } case 0x55 { // OP_SSTORE @@ -671,8 +645,8 @@ for { } true { } { let key, value, gasSpent popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) ip := add(ip, 1) { @@ -709,7 +683,7 @@ for { } true { } { let counter - counter, sp := popStackItem(sp, evmGasLeft) + counter, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) @@ -729,8 +703,8 @@ for { } true { } { let counter, b popStackCheck(sp, evmGasLeft, 2) - counter, sp := popStackItemWithoutCheck(sp) - b, sp := popStackItemWithoutCheck(sp) + counter, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + b, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) if iszero(b) { ip := add(ip, 1) @@ -754,7 +728,7 @@ for { } true { } { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft, stackHead) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft,2) @@ -763,13 +737,13 @@ for { } true { } { size := mload(MEM_OFFSET()) size := shl(5,size) - sp := pushStackItem(sp,size, evmGasLeft) + sp, stackHead := pushStackItem(sp,size, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5A { // OP_GAS evmGasLeft := chargeGas(evmGasLeft, 2) - sp := pushStackItem(sp, evmGasLeft, evmGasLeft) + sp, stackHead := pushStackItem(sp, evmGasLeft, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5B { // OP_JUMPDEST @@ -779,11 +753,11 @@ for { } true { } { case 0x5C { // OP_TLOAD evmGasLeft := chargeGas(evmGasLeft, 100) - let key - popStackCheck(sp, evmGasLeft, 1) - key, sp := popStackItemWithoutCheck(sp) + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - sp := pushStackItemWithoutCheck(sp, tload(key)) + stackHead := tload(stackHead) ip := add(ip, 1) } case 0x5D { // OP_TSTORE @@ -795,8 +769,8 @@ for { } true { } { let key, value popStackCheck(sp, evmGasLeft, 2) - key, sp := popStackItemWithoutCheck(sp) - value, sp := popStackItemWithoutCheck(sp) + key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) tstore(key, value) ip := add(ip, 1) @@ -804,9 +778,9 @@ for { } true { } { case 0x5E { // OP_MCOPY let destOffset, offset, size popStackCheck(sp, evmGasLeft, 3) - destOffset, sp := popStackItemWithoutCheck(sp) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkOverflow(destOffset, size, evmGasLeft) @@ -824,7 +798,7 @@ for { } true { } { let value := 0 - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x60 { // OP_PUSH1 @@ -833,7 +807,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,1) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x61 { // OP_PUSH2 @@ -842,7 +816,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,2) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 2) } case 0x62 { // OP_PUSH3 @@ -851,7 +825,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,3) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 3) } case 0x63 { // OP_PUSH4 @@ -860,7 +834,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,4) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 4) } case 0x64 { // OP_PUSH5 @@ -869,7 +843,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,5) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 5) } case 0x65 { // OP_PUSH6 @@ -878,7 +852,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,6) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 6) } case 0x66 { // OP_PUSH7 @@ -887,7 +861,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,7) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 7) } case 0x67 { // OP_PUSH8 @@ -896,7 +870,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,8) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 8) } case 0x68 { // OP_PUSH9 @@ -905,7 +879,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,9) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 9) } case 0x69 { // OP_PUSH10 @@ -914,7 +888,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,10) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 10) } case 0x6A { // OP_PUSH11 @@ -923,7 +897,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,11) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 11) } case 0x6B { // OP_PUSH12 @@ -932,7 +906,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,12) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 12) } case 0x6C { // OP_PUSH13 @@ -941,7 +915,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,13) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 13) } case 0x6D { // OP_PUSH14 @@ -950,7 +924,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,14) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 14) } case 0x6E { // OP_PUSH15 @@ -959,7 +933,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,15) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 15) } case 0x6F { // OP_PUSH16 @@ -968,7 +942,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,16) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 16) } case 0x70 { // OP_PUSH17 @@ -977,7 +951,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,17) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 17) } case 0x71 { // OP_PUSH18 @@ -986,7 +960,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,18) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 18) } case 0x72 { // OP_PUSH19 @@ -995,7 +969,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,19) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 19) } case 0x73 { // OP_PUSH20 @@ -1004,7 +978,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,20) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 20) } case 0x74 { // OP_PUSH21 @@ -1013,7 +987,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,21) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 21) } case 0x75 { // OP_PUSH22 @@ -1022,7 +996,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,22) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 22) } case 0x76 { // OP_PUSH23 @@ -1031,7 +1005,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,23) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 23) } case 0x77 { // OP_PUSH24 @@ -1040,7 +1014,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,24) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 24) } case 0x78 { // OP_PUSH25 @@ -1049,7 +1023,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,25) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 25) } case 0x79 { // OP_PUSH26 @@ -1058,7 +1032,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,26) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 26) } case 0x7A { // OP_PUSH27 @@ -1067,7 +1041,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,27) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 27) } case 0x7B { // OP_PUSH28 @@ -1076,7 +1050,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,28) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 28) } case 0x7C { // OP_PUSH29 @@ -1085,7 +1059,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,29) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 29) } case 0x7D { // OP_PUSH30 @@ -1094,7 +1068,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,30) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 30) } case 0x7E { // OP_PUSH31 @@ -1103,7 +1077,7 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,31) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 31) } case 0x7F { // OP_PUSH32 @@ -1112,135 +1086,136 @@ for { } true { } { ip := add(ip, 1) let value := readBytes(ip,maxAcceptablePos,32) - sp := pushStackItem(sp, value, evmGasLeft) + sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) ip := add(ip, 32) } case 0x80 { // OP_DUP1 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 1) + evmGasLeft := chargeGas(evmGasLeft, 3) + sp, stackHead := pushStackItem(sp, stackHead, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 2) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x82 { // OP_DUP3 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 3) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x83 { // OP_DUP4 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 4) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x84 { // OP_DUP5 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 5) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x85 { // OP_DUP6 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 6) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x86 { // OP_DUP7 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 7) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x87 { // OP_DUP8 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 8) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x88 { // OP_DUP9 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 9) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x89 { // OP_DUP10 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 10) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x8A { // OP_DUP11 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 11) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x8B { // OP_DUP12 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 12) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x8C { // OP_DUP13 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 13) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x8D { // OP_DUP14 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 14) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x8E { // OP_DUP15 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 15) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x8F { // OP_DUP16 - sp, evmGasLeft := dupStackItem(sp, evmGasLeft, 16) + sp, evmGasLeft, stackHead := dupStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0x90 { // OP_SWAP1 - evmGasLeft := swapStackItem(sp, evmGasLeft, 1) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 1, stackHead) ip := add(ip, 1) } case 0x91 { // OP_SWAP2 - evmGasLeft := swapStackItem(sp, evmGasLeft, 2) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 2, stackHead) ip := add(ip, 1) } case 0x92 { // OP_SWAP3 - evmGasLeft := swapStackItem(sp, evmGasLeft, 3) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 3, stackHead) ip := add(ip, 1) } case 0x93 { // OP_SWAP4 - evmGasLeft := swapStackItem(sp, evmGasLeft, 4) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 4, stackHead) ip := add(ip, 1) } case 0x94 { // OP_SWAP5 - evmGasLeft := swapStackItem(sp, evmGasLeft, 5) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 5, stackHead) ip := add(ip, 1) } case 0x95 { // OP_SWAP6 - evmGasLeft := swapStackItem(sp, evmGasLeft, 6) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 6, stackHead) ip := add(ip, 1) } case 0x96 { // OP_SWAP7 - evmGasLeft := swapStackItem(sp, evmGasLeft, 7) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 7, stackHead) ip := add(ip, 1) } case 0x97 { // OP_SWAP8 - evmGasLeft := swapStackItem(sp, evmGasLeft, 8) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 8, stackHead) ip := add(ip, 1) } case 0x98 { // OP_SWAP9 - evmGasLeft := swapStackItem(sp, evmGasLeft, 9) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 9, stackHead) ip := add(ip, 1) } case 0x99 { // OP_SWAP10 - evmGasLeft := swapStackItem(sp, evmGasLeft, 10) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 10, stackHead) ip := add(ip, 1) } case 0x9A { // OP_SWAP11 - evmGasLeft := swapStackItem(sp, evmGasLeft, 11) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 11, stackHead) ip := add(ip, 1) } case 0x9B { // OP_SWAP12 - evmGasLeft := swapStackItem(sp, evmGasLeft, 12) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 12, stackHead) ip := add(ip, 1) } case 0x9C { // OP_SWAP13 - evmGasLeft := swapStackItem(sp, evmGasLeft, 13) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 13, stackHead) ip := add(ip, 1) } case 0x9D { // OP_SWAP14 - evmGasLeft := swapStackItem(sp, evmGasLeft, 14) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 14, stackHead) ip := add(ip, 1) } case 0x9E { // OP_SWAP15 - evmGasLeft := swapStackItem(sp, evmGasLeft, 15) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 15, stackHead) ip := add(ip, 1) } case 0x9F { // OP_SWAP16 - evmGasLeft := swapStackItem(sp, evmGasLeft, 16) + evmGasLeft, stackHead := swapStackItem(sp, evmGasLeft, 16, stackHead) ip := add(ip, 1) } case 0xA0 { // OP_LOG0 @@ -1252,8 +1227,8 @@ for { } true { } { let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1274,8 +1249,8 @@ for { } true { } { let offset, size popStackCheck(sp, evmGasLeft, 3) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1287,7 +1262,7 @@ for { } true { } { { let topic1 - topic1, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log1(add(offset, MEM_OFFSET_INNER()), size, topic1) } ip := add(ip, 1) @@ -1300,8 +1275,8 @@ for { } true { } { let offset, size popStackCheck(sp, evmGasLeft, 4) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1313,8 +1288,8 @@ for { } true { } { { let topic1, topic2 - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) } ip := add(ip, 1) @@ -1328,8 +1303,8 @@ for { } true { } { let offset, size popStackCheck(sp, evmGasLeft, 5) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1341,9 +1316,9 @@ for { } true { } { { let topic1, topic2, topic3 - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) } ip := add(ip, 1) @@ -1357,8 +1332,8 @@ for { } true { } { let offset, size popStackCheck(sp, evmGasLeft, 6) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1370,36 +1345,35 @@ for { } true { } { { let topic1, topic2, topic3, topic4 - topic1, sp := popStackItemWithoutCheck(sp) - topic2, sp := popStackItemWithoutCheck(sp) - topic3, sp := popStackItemWithoutCheck(sp) - topic4, sp := popStackItemWithoutCheck(sp) + topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) 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) + evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, isStatic, stackHead) ip := add(ip, 1) } case 0xF1 { // OP_CALL // A function was implemented in order to avoid stack depth errors. switch isStatic case 0 { - evmGasLeft, sp := performCall(sp, evmGasLeft) + evmGasLeft, sp, stackHead := performCall(sp, evmGasLeft, stackHead) } default { - evmGasLeft, sp := performStaticCall(sp, evmGasLeft) + evmGasLeft, sp, stackHead := performStaticCall(sp, evmGasLeft, stackHead) } - ip := add(ip, 1) } case 0xF3 { // OP_RETURN let offset, size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset, size, evmGasLeft) evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) @@ -1413,27 +1387,27 @@ for { } true { } { break } case 0xF4 { // OP_DELEGATECALL - evmGasLeft, sp := performDelegateCall(sp, evmGasLeft, isStatic) + evmGasLeft, sp, stackHead := performDelegateCall(sp, evmGasLeft, isStatic, stackHead) ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 let result, addr - evmGasLeft, sp, result, addr := performCreate2(evmGasLeft, sp, isStatic) + evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) switch result - case 0 { sp := pushStackItem(sp, 0, evmGasLeft) } - default { sp := pushStackItem(sp, addr, evmGasLeft) } + case 0 { sp, stackHead := pushStackItem(sp, 0, evmGasLeft, stackHead) } + default { sp, stackHead := pushStackItem(sp, addr, evmGasLeft, stackHead) } ip := add(ip, 1) } case 0xFA { // OP_STATICCALL - evmGasLeft, sp := performStaticCall(sp, evmGasLeft) + evmGasLeft, sp, stackHead := performStaticCall(sp,evmGasLeft, stackHead) ip := add(ip, 1) } case 0xFD { // OP_REVERT let offset,size popStackCheck(sp, evmGasLeft, 2) - offset, sp := popStackItemWithoutCheck(sp) - size, sp := popStackItemWithoutCheck(sp) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkOverflow(offset,size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) @@ -1451,9 +1425,340 @@ for { } true { } { revertWithGas(evmGasLeft) } + case 0x0C { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x0D { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x0E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x0F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x1E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x1F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x21 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x22 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x23 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x24 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x25 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x26 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x27 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x28 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x29 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2A { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2B { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2C { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2D { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x2F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x49 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4A { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4B { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4C { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4D { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4E { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0x4F { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xA9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xAF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xB9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xBF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xC9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xCF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xD9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDD { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xDF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE0 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE1 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE3 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE4 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE5 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xE9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEA { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xED { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEE { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xEF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF2 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF6 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF7 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF8 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xF9 { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xFB { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xFC { // Unused opcode + $llvm_NoInline_llvm$_revert() + } + case 0xFF { // Unused opcode + $llvm_NoInline_llvm$_revert() + } default { - printString("INVALID OPCODE") - printHex(opcode) - revert(0, 0) + $llvm_NoInline_llvm$_revert() } } From 28ab977bf050ef9281a16abfd4544be42e82e069 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 22 Oct 2024 13:42:48 +0200 Subject: [PATCH 083/183] chore(EVM): Move unused opcodes to template (#960) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 2 + .../evm-emulator/EvmEmulatorLoop.template.yul | 335 +----------------- .../EvmEmulatorLoopUnusedOpcodes.template.yul | 333 +++++++++++++++++ 4 files changed, 339 insertions(+), 335 deletions(-) create mode 100644 system-contracts/evm-emulator/EvmEmulatorLoopUnusedOpcodes.template.yul diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 86ff1c676..a230370db 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000d5550ffee2b5db585660d0c1a8c4511192658932adef00c322cd518bd29", - "sourceCodeHash": "0x414eb35f4032b71e34964e8b6e28db3bdc2b3e2b5801893dfb5c7365949483c6" + "bytecodeHash": "0x01000d55dfce9cbc03935c1860b59abc641f77e7a0fe2b3d94bb7656a8adf804", + "sourceCodeHash": "0xc0fec0aeaacbe9a335187c1025d8fd21b2ee8bc5a2bbbed589cf414dc1d5ed16" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 86e6a3a3a..c25fffff2 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -2746,6 +2746,7 @@ object "EvmEmulator" { revertWithGas(evmGasLeft) } + // We explicitly add unused opcodes to optimize the jump table by compiler. case 0x0C { // Unused opcode $llvm_NoInline_llvm$_revert() } @@ -5816,6 +5817,7 @@ object "EvmEmulator" { revertWithGas(evmGasLeft) } + // We explicitly add unused opcodes to optimize the jump table by compiler. case 0x0C { // Unused opcode $llvm_NoInline_llvm$_revert() } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index d20f73be4..36bf5f53d 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -1425,339 +1425,8 @@ for { } true { } { revertWithGas(evmGasLeft) } - case 0x0C { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x0D { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x0E { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x0F { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x1E { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x1F { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x21 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x22 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x23 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x24 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x25 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x26 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x27 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x28 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x29 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x2A { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x2B { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x2C { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x2D { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x2E { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x2F { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x49 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x4A { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x4B { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x4C { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x4D { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x4E { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0x4F { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xA5 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xA6 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xA7 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xA8 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xA9 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xAA { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xAB { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xAC { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xAD { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xAE { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xAF { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xB0 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xB1 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xB2 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xB3 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xB4 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xB5 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xB6 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xB7 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xB8 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xB9 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xBA { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xBB { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xBC { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xBD { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xBE { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xBF { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xC0 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xC1 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xC2 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xC3 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xC4 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xC5 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xC6 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xC7 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xC8 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xC9 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xCA { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xCB { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xCC { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xCD { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xCE { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xCF { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xD0 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xD1 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xD2 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xD3 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xD4 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xD5 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xD6 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xD7 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xD8 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xD9 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xDA { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xDB { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xDC { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xDD { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xDE { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xDF { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xE0 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xE1 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xE2 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xE3 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xE4 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xE5 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xE6 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xE7 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xE8 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xE9 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xEA { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xEB { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xEC { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xED { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xEE { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xEF { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xF2 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xF6 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xF7 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xF8 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xF9 { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xFB { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xFC { // Unused opcode - $llvm_NoInline_llvm$_revert() - } - case 0xFF { // Unused opcode - $llvm_NoInline_llvm$_revert() - } + // We explicitly add unused opcodes to optimize the jump table by compiler. + default { $llvm_NoInline_llvm$_revert() } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoopUnusedOpcodes.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoopUnusedOpcodes.template.yul new file mode 100644 index 000000000..03c163bdd --- /dev/null +++ b/system-contracts/evm-emulator/EvmEmulatorLoopUnusedOpcodes.template.yul @@ -0,0 +1,333 @@ +case 0x0C { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x0D { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x0E { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x0F { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x1E { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x1F { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x21 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x22 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x23 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x24 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x25 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x26 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x27 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x28 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x29 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x2A { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x2B { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x2C { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x2D { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x2E { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x2F { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x49 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x4A { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x4B { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x4C { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x4D { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x4E { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0x4F { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xA5 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xA6 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xA7 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xA8 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xA9 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xAA { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xAB { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xAC { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xAD { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xAE { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xAF { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xB0 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xB1 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xB2 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xB3 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xB4 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xB5 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xB6 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xB7 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xB8 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xB9 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xBA { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xBB { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xBC { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xBD { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xBE { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xBF { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xC0 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xC1 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xC2 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xC3 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xC4 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xC5 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xC6 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xC7 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xC8 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xC9 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xCA { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xCB { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xCC { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xCD { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xCE { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xCF { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xD0 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xD1 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xD2 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xD3 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xD4 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xD5 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xD6 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xD7 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xD8 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xD9 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xDA { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xDB { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xDC { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xDD { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xDE { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xDF { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xE0 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xE1 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xE2 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xE3 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xE4 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xE5 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xE6 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xE7 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xE8 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xE9 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xEA { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xEB { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xEC { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xED { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xEE { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xEF { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xF2 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xF6 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xF7 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xF8 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xF9 { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xFB { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xFC { // Unused opcode + $llvm_NoInline_llvm$_revert() +} +case 0xFF { // Unused opcode + $llvm_NoInline_llvm$_revert() +} \ No newline at end of file From daba783e8ee9ad578a69a1a15716b5fd3680a5bd Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 22 Oct 2024 14:46:20 +0200 Subject: [PATCH 084/183] chore(EVM): Simplify system calls in emulator (#961) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 230 ++++-------------- .../EvmEmulatorFunctions.template.yul | 115 ++------- 3 files changed, 65 insertions(+), 284 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index a230370db..8d861a7f4 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000d55dfce9cbc03935c1860b59abc641f77e7a0fe2b3d94bb7656a8adf804", - "sourceCodeHash": "0xc0fec0aeaacbe9a335187c1025d8fd21b2ee8bc5a2bbbed589cf414dc1d5ed16" + "bytecodeHash": "0x01000d55ae987dc71cd41cf33a45bec8127083a2b6d4822883f3dba6e93dec70", + "sourceCodeHash": "0x1b7b331c17f27268bf7ca841e0742393e4708f14ea33ad231f9c280ea895bccd" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index c25fffff2..911fa083d 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -316,25 +316,7 @@ object "EvmEmulator" { // non-standard selector 0x04 mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 1, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) let _returndatasize := returndatasize() if _returndatasize { @@ -571,25 +553,7 @@ object "EvmEmulator" { mstore(1, key) mstore(33,currentValue) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 65, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) if returndatasize() { isWarm := true @@ -598,28 +562,28 @@ object "EvmEmulator" { } } - function getFarCallABI( - dataOffset, - memoryPage, - dataStart, + function performSystemCall( + to, dataLength, - gasPassed, - shardId, - forwardingMode, - isConstructorCall, - isSystemCall ) -> ret { - let farCallAbi := 0 - farCallAbi := or(farCallAbi, dataOffset) - farCallAbi := or(farCallAbi, shl(64, dataStart)) + let farCallAbi := shl(248, 1) // system call + // dataOffset is 0 + // dataStart is 0 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 + farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + // shardId is 0 + // forwardingMode is 0 + // not constructor call + + 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 addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) -> newOffset,newSize { newOffset := offset newSize := size @@ -641,25 +605,7 @@ object "EvmEmulator" { // addr is packed in the same word with selector mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 32, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32) if returndatasize() { isWarm := true @@ -705,26 +651,7 @@ object "EvmEmulator" { mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) mstore(32, _passGas) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 64, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) } // Each evm gas is 5 zkEVM one @@ -3387,25 +3314,7 @@ object "EvmEmulator" { // non-standard selector 0x04 mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 1, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) let _returndatasize := returndatasize() if _returndatasize { @@ -3642,25 +3551,7 @@ object "EvmEmulator" { mstore(1, key) mstore(33,currentValue) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 65, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) if returndatasize() { isWarm := true @@ -3669,28 +3560,28 @@ object "EvmEmulator" { } } - function getFarCallABI( - dataOffset, - memoryPage, - dataStart, + function performSystemCall( + to, dataLength, - gasPassed, - shardId, - forwardingMode, - isConstructorCall, - isSystemCall ) -> ret { - let farCallAbi := 0 - farCallAbi := or(farCallAbi, dataOffset) - farCallAbi := or(farCallAbi, shl(64, dataStart)) + let farCallAbi := shl(248, 1) // system call + // dataOffset is 0 + // dataStart is 0 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 + farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + // shardId is 0 + // forwardingMode is 0 + // not constructor call + + 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 addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) -> newOffset,newSize { newOffset := offset newSize := size @@ -3712,25 +3603,7 @@ object "EvmEmulator" { // addr is packed in the same word with selector mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 32, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32) if returndatasize() { isWarm := true @@ -3776,26 +3649,7 @@ object "EvmEmulator" { mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) mstore(32, _passGas) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 64, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) } // Each evm gas is 5 zkEVM one diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 810dbfa70..3dfbcd3a8 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -266,25 +266,7 @@ function consumeEvmFrame() -> passGas, isStatic, callerEVM { // non-standard selector 0x04 mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 1, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) let _returndatasize := returndatasize() if _returndatasize { @@ -521,25 +503,7 @@ function warmSlot(key,currentValue) -> isWarm, originalValue { mstore(1, key) mstore(33,currentValue) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 65, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) if returndatasize() { isWarm := true @@ -548,28 +512,28 @@ function warmSlot(key,currentValue) -> isWarm, originalValue { } } -function getFarCallABI( - dataOffset, - memoryPage, - dataStart, +function performSystemCall( + to, dataLength, - gasPassed, - shardId, - forwardingMode, - isConstructorCall, - isSystemCall ) -> ret { - let farCallAbi := 0 - farCallAbi := or(farCallAbi, dataOffset) - farCallAbi := or(farCallAbi, shl(64, dataStart)) + let farCallAbi := shl(248, 1) // system call + // dataOffset is 0 + // dataStart is 0 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 + farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + // shardId is 0 + // forwardingMode is 0 + // not constructor call + + 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 addGasIfEvmRevert(isCallerEVM,offset,size,evmGasLeft) -> newOffset,newSize { newOffset := offset newSize := size @@ -591,25 +555,7 @@ function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { // addr is packed in the same word with selector mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 32, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32) if returndatasize() { isWarm := true @@ -655,26 +601,7 @@ function _pushEVMFrame(_passGas, _isStatic) { mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) mstore(32, _passGas) - let farCallAbi := getFarCallABI( - 0, - 0, - 0, - 64, - 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) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) } // Each evm gas is 5 zkEVM one From ddaad7d1cd752e3e5f7b9f5c44eafecae6835e5c Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 22 Oct 2024 22:00:43 +0200 Subject: [PATCH 085/183] feat(EVM): Switch EVM emulation in ContractDeployer constructor (#962) --- system-contracts/SystemContractsHashes.json | 32 +++++++------- .../contracts/ContractDeployer.sol | 44 +++++++++++++++++-- .../contracts/SystemContractErrors.sol | 4 ++ .../interfaces/IContractDeployer.sol | 13 ++++++ .../test/ContractDeployer.spec.ts | 12 ++++- .../test/precompiles/Identity.spec.ts | 2 +- system-contracts/test/shared/utils.ts | 14 ++++-- 7 files changed, 95 insertions(+), 26 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 8d861a7f4..cc383827e 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": "0x010000770d1ad5dccb505d6d550d688408f162f13bde5dab6628b9739c1507ae", + "bytecodeHash": "0x01000077028e51aec3a82c209b999e201eb877e8269962246b85008b9de1c021", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f14b3e5ab60d5e53b4ef8d08e5abc0bdfba461705d3bf8ddf37cf42b8e", + "bytecodeHash": "0x010006f134d6b56f5bb2917ab70bdf76126b271242f73b794453d6b912144a87", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x01000047067f0bd2667d64ac7edd106c5c6a40fb287b70314984dd6e32ba6be1", + "bytecodeHash": "0x010000479bc5a91bc0579990aa4d021696050b245fd3345e4e53e60b64138ee2", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013f6a3a7d0769f64451d185895c3a839047c1400bfedae19b03ee8a1cf3", + "bytecodeHash": "0x0100013f862bf8b79fa219aeadcb67880bc97b6648cfe157733922e174cccca4", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010005c16efab28191218d32be99762e38165e1278b1341fd6f4fda67a52023e", - "sourceCodeHash": "0x8fecd5c1284ade078f91ba270a2c0a96e91475861cceff7304d17469fd8e0ef2" + "bytecodeHash": "0x010005db2681b1835b7de4cca51ae5dd08b63ab5fd37c990e359070221fba2f4", + "sourceCodeHash": "0x834845a85ef7426c763c783dfc56ed994d3015f8ea8a6fdc5c686c0cc279d002" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003f0719fa16f261fff54d3b54e99538342210f6048c97f51a32abcda54b", + "bytecodeHash": "0x0100003fd3dcd14aa3d6ccae73e6e559d8e127cab59edc880728740e3a4e2f61", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x01000503995a56fbbabfd01df28d096f83ad1ebe9c5b2943782fdacec930f141", + "bytecodeHash": "0x01000503a1205f3d5eacfb84fae1746fca2f326870cecdc7d96471d90a08f472", "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { @@ -59,56 +59,56 @@ "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033006022a456ca30686147e715d6eaa743f5b735c3de6c320e471a04b6", + "bytecodeHash": "0x01000033d4ca4f62a4216a848300c3277afb6fe332c2d1d0e52217df01a3609c", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000c1e4010651c2ef7aac70beb479d68dc23272349289693718dbb7545a91", + "bytecodeHash": "0x010000c1790b5f0a79505c94fae292748850690e0569b27dba3de95899d8de1e", "sourceCodeHash": "0xeb83e3a2ea2f50b93122363b8dd56fbcfe821d11723d849eecbde3d6af1147de" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010002659c6c2e6e0e44a99ec4b4b6c69ff8ca0d6c2b9be0de28d687fdc20140", + "bytecodeHash": "0x0100026586b7819633ded9a96621293986d59d63328457b9a33caba9018dc857", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f36ab487155ade735537ce9aac7e0c231d1f52653851de4bc905cf9769", + "bytecodeHash": "0x010000f307578eb3a57c2373e597fff622c6b4b15d76ed730f445e51a73f6fa4", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x01000059d2e4402d061635ca1ee1a28d2759f452536ba86aefd9add8a7267b5a", + "bytecodeHash": "0x01000059376102d591ee9804ef9e0e6557c9b1fa231dced5635f87966e69a252", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cf93373b31cda60ce1ae9eeb9c0b7185b4b9dd4ee44f0d51f0983f13f5", + "bytecodeHash": "0x010000cf6479ebeb83e1ab27fcf3cbf7d04b9afa02357a9c88485c93076e2589", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041c0b7009011f319f2119be4aa438ad575e3ef9c250d6b309242bf18ba", + "bytecodeHash": "0x01000041a140ce3229704f5d7b25181dcc3df3a16d4f52f9d794bc964aef8d17", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a516977d7a6f0bd69e75da6d4d9ff179faf0318fd86cb91fcfb09f3c69", + "bytecodeHash": "0x010001a5ca16a30d14b5b2bc67173b8d30b728d6e79a3ae142925c3af3cd3019", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index ba0644b6d..e52260e8c 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -12,7 +12,7 @@ import {Utils} from "./libraries/Utils.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; 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 {Unauthorized, InvalidAllowedBytecodeTypesMode, InvalidNonceOrderingChange, ValueMismatch, EmptyBytes32, EVMEmulationNotSupported, NotAllowedToDeployInKernelSpace, HashIsNonZero, NonEmptyAccount, UnknownCodeHash, NonEmptyMsgValue} from "./SystemContractErrors.sol"; /** * @author Matter Labs @@ -29,7 +29,8 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { mapping(address => AccountInfo) internal accountInfo; uint256 private constant EVM_HASHES_PREFIX = 1 << 254; - uint256 private constant CONSTRUCTOR_RETURN_GAS_SLOT = 1; + uint256 private constant CONSTRUCTOR_RETURN_GAS_TSLOT = 1; + uint256 private constant ALLOWED_BYTECODE_TYPES_MODE_SLOT = 2; modifier onlySelf() { if (msg.sender != address(this)) { @@ -38,13 +39,38 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _; } + /// @notice Can be used only during upgrades. + /// @param newAllowedBytecodeTypes The new allowed bytecode types mode. + /// @dev Changes what types of bytecodes are allowed to be deployed on the chain. + constructor(uint256 newAllowedBytecodeTypes) { + if ( + newAllowedBytecodeTypes != uint256(AllowedBytecodeTypes.EraVm) && + newAllowedBytecodeTypes != uint256(AllowedBytecodeTypes.EraVmAndEVM) + ) { + revert InvalidAllowedBytecodeTypesMode(); + } + + if (uint256(_getAllowedBytecodeTypesMode()) != newAllowedBytecodeTypes) { + assembly { + sstore(ALLOWED_BYTECODE_TYPES_MODE_SLOT, newAllowedBytecodeTypes) + } + + emit AllowedBytecodeTypesModeUpdated(AllowedBytecodeTypes(newAllowedBytecodeTypes)); + } + } + function evmCodeHash(address _address) external view returns (bytes32 _hash) { _hash = _getEvmCodeHash(_address); } + /// @notice Returns what types of bytecode are allowed to be deployed on this chain + function allowedBytecodeTypesToDeploy() external view returns (AllowedBytecodeTypes mode) { + mode = _getAllowedBytecodeTypesMode(); + } + function constructorReturnGas() external view returns (uint256 returnGas) { assembly { - returnGas := tload(CONSTRUCTOR_RETURN_GAS_SLOT) + returnGas := tload(CONSTRUCTOR_RETURN_GAS_TSLOT) } } @@ -336,6 +362,10 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } function _evmDeployOnAddress(address _newAddress, bytes calldata _initCode) internal { + if (_getAllowedBytecodeTypesMode() != AllowedBytecodeTypes.EraVmAndEVM) { + revert EVMEmulationNotSupported(); + } + // 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); @@ -516,7 +546,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _setEvmCodeHash(_newAddress, evmBytecodeHash); assembly { - tstore(CONSTRUCTOR_RETURN_GAS_SLOT, constructorReturnGas) + tstore(CONSTRUCTOR_RETURN_GAS_TSLOT, constructorReturnGas) } emit ContractDeployed(_sender, evmBytecodeHash, _newAddress); @@ -535,4 +565,10 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _hash := sload(slot) } } + + function _getAllowedBytecodeTypesMode() internal view returns (AllowedBytecodeTypes mode) { + assembly { + mode := sload(ALLOWED_BYTECODE_TYPES_MODE_SLOT) + } + } } diff --git a/system-contracts/contracts/SystemContractErrors.sol b/system-contracts/contracts/SystemContractErrors.sol index 49dee4655..4e5b5bfbe 100644 --- a/system-contracts/contracts/SystemContractErrors.sol +++ b/system-contracts/contracts/SystemContractErrors.sol @@ -34,6 +34,8 @@ error EmptyVirtualBlocks(); error EncodedAndRealBytecodeChunkNotEqual(uint64 expected, uint64 provided); // 0x2bfbfc11 error EncodedLengthNotFourTimesSmallerThanOriginal(); +// 0xb9e6e31f +error EVMEmulationNotSupported(); // 0xe95a1fbe error FailedToChargeGas(); // 0x1f70c58f @@ -52,6 +54,8 @@ error IndexSizeError(); error InsufficientFunds(uint256 required, uint256 actual); // 0x1c26714c error InsufficientGas(); +// 0x8322ca79 +error InvalidAllowedBytecodeTypesMode(); // 0xae962d4e error InvalidCall(); // 0x6a84bc39 diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index 9046e7921..c4b090a58 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -25,6 +25,14 @@ interface IContractDeployer { Arbitrary } + /// @notice Defines what types of bytecode are allowed to be deployed on this chain + /// - `EraVm` means that only native contracts can be deployed + /// - `EraVmAndEVM` means that native contracts and EVM contracts can be deployed + enum AllowedBytecodeTypes { + EraVm, + EraVmAndEVM + } + struct AccountInfo { AccountAbstractionVersion supportedAAVersion; AccountNonceOrdering nonceOrdering; @@ -40,6 +48,11 @@ interface IContractDeployer { event AccountVersionUpdated(address indexed accountAddress, AccountAbstractionVersion aaVersion); + event AllowedBytecodeTypesModeUpdated(AllowedBytecodeTypes mode); + + /// @notice Returns what types of bytecode are allowed to be deployed on this chain + function allowedBytecodeTypesToDeploy() external view returns (AllowedBytecodeTypes mode); + function getNewAddressCreate2( address _sender, bytes32 _bytecodeHash, diff --git a/system-contracts/test/ContractDeployer.spec.ts b/system-contracts/test/ContractDeployer.spec.ts index bcae882c0..569a9f9b5 100644 --- a/system-contracts/test/ContractDeployer.spec.ts +++ b/system-contracts/test/ContractDeployer.spec.ts @@ -43,7 +43,7 @@ describe("ContractDeployer tests", function () { await prepareEnvironment(); wallet = getWallets()[0]; - await deployContractOnAddress(TEST_DEPLOYER_SYSTEM_CONTRACT_ADDRESS, "ContractDeployer"); + await deployContractOnAddress(TEST_DEPLOYER_SYSTEM_CONTRACT_ADDRESS, "ContractDeployer", false); contractDeployer = ContractDeployerFactory.connect(TEST_DEPLOYER_SYSTEM_CONTRACT_ADDRESS, wallet); const contractDeployerSystemCallContract = await deployContract("SystemCaller", [contractDeployer.address]); @@ -66,6 +66,16 @@ describe("ContractDeployer tests", function () { }); }); + describe("constructor", function () { + it("successfully updated allowedBytecodeTypesToDeploy", async () => { + const newContractDeployer = await deployContract("ContractDeployer", [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + ]); + + expect(await newContractDeployer.allowedBytecodeTypesToDeploy()).to.be.eq(1); + }); + }); + describe("updateAccountVersion", function () { it("non system call failed", async () => { await expect(contractDeployer.updateAccountVersion(AA_VERSION_NONE)).to.be.revertedWithCustomError( diff --git a/system-contracts/test/precompiles/Identity.spec.ts b/system-contracts/test/precompiles/Identity.spec.ts index 7c74550ca..7da2befa0 100644 --- a/system-contracts/test/precompiles/Identity.spec.ts +++ b/system-contracts/test/precompiles/Identity.spec.ts @@ -2,7 +2,7 @@ import { expect } from "chai"; import type { Contract } from "zksync-ethers"; import { callFallback, deployContractYul } from "../shared/utils"; -describe.only("EcAdd tests", function () { +describe("Identity tests", function () { let identity: Contract; before(async () => { diff --git a/system-contracts/test/shared/utils.ts b/system-contracts/test/shared/utils.ts index c382301a1..1e434a0a7 100644 --- a/system-contracts/test/shared/utils.ts +++ b/system-contracts/test/shared/utils.ts @@ -117,9 +117,14 @@ async function deployBytecode(bytecode: string): Promise { ); } -export async function deployContractOnAddress(address: string, name: string) { +export async function deployContractOnAddress( + address: string, + name: string, + callConstructor: boolean = true, + input = "0x" +) { const artifact = await loadArtifact(name); - await setCode(address, artifact.bytecode, true); + await setCode(address, artifact.bytecode, callConstructor, input); } export async function publishBytecode(bytecode: BytesLike) { @@ -139,7 +144,7 @@ export async function getCode(address: string): Promise { } // Force deploy bytecode on the address -export async function setCode(address: string, bytecode: BytesLike, callConstructor: boolean = false) { +export async function setCode(address: string, bytecode: BytesLike, callConstructor: boolean = false, input = "0x") { // TODO: think about factoryDeps with eth_sendTransaction try { // publish bytecode in a separate tx @@ -156,8 +161,9 @@ export async function setCode(address: string, bytecode: BytesLike, callConstruc newAddress: address, callConstructor, value: 0, - input: "0x", + input, }; + await deployerContract.forceDeployOnAddress(deployment, ethers.constants.AddressZero); } From 2f3f35d1f4170459adb12918932da8bd6003c76c Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 23 Oct 2024 11:13:51 +0200 Subject: [PATCH 086/183] chore(EVM): Merge dev (#966) Signed-off-by: Danil Co-authored-by: kelemeno <34402761+kelemeno@users.noreply.github.com> Co-authored-by: Danil Co-authored-by: Vlad Bochok <41153528+vladbochok@users.noreply.github.com> From 44207551d7dd5581200a1e6e29c373b6d7c4747e Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 23 Oct 2024 11:41:50 +0200 Subject: [PATCH 087/183] chore(EVM): Cleanup in contracts (#967) --- l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol | 11 ++++++----- .../contracts/upgrades/ZkSyncUpgradeErrors.sol | 2 ++ system-contracts/SystemContractsHashes.json | 4 ++-- system-contracts/contracts/ContractDeployer.sol | 2 -- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol b/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol index c7f2453e3..85b38fcfc 100644 --- a/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol +++ b/l1-contracts/contracts/upgrades/BaseZkSyncUpgrade.sol @@ -1,7 +1,5 @@ // 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"; @@ -13,7 +11,7 @@ import {L2ContractHelper} from "../common/libraries/L2ContractHelper.sol"; import {TransactionValidator} from "../state-transition/libraries/TransactionValidator.sol"; import {MAX_NEW_FACTORY_DEPS, SYSTEM_UPGRADE_L2_TX_TYPE, MAX_ALLOWED_MINOR_VERSION_DELTA} from "../common/Config.sol"; import {L2CanonicalTransaction} from "../common/Messaging.sol"; -import {ProtocolVersionMinorDeltaTooBig, TimeNotReached, InvalidTxType, L2UpgradeNonceNotEqualToNewProtocolVersion, TooManyFactoryDeps, UnexpectedNumberOfFactoryDeps, ProtocolVersionTooSmall, PreviousUpgradeNotFinalized, PreviousUpgradeNotCleaned, L2BytecodeHashMismatch, PatchCantSetUpgradeTxn, PreviousProtocolMajorVersionNotZero, NewProtocolMajorVersionNotZero, PatchUpgradeCantSetDefaultAccount, PatchUpgradeCantSetBootloader} from "./ZkSyncUpgradeErrors.sol"; +import {ProtocolVersionMinorDeltaTooBig, TimeNotReached, InvalidTxType, L2UpgradeNonceNotEqualToNewProtocolVersion, TooManyFactoryDeps, UnexpectedNumberOfFactoryDeps, ProtocolVersionTooSmall, PreviousUpgradeNotFinalized, PreviousUpgradeNotCleaned, L2BytecodeHashMismatch, PatchCantSetUpgradeTxn, PreviousProtocolMajorVersionNotZero, NewProtocolMajorVersionNotZero, PatchUpgradeCantSetDefaultAccount, PatchUpgradeCantSetBootloader, PatchUpgradeCantSetEvmEmulator} from "./ZkSyncUpgradeErrors.sol"; import {SemVer} from "../common/libraries/SemVer.sol"; /// @notice The struct that represents the upgrade proposal. @@ -21,6 +19,7 @@ import {SemVer} from "../common/libraries/SemVer.sol"; /// @param factoryDeps The list of factory deps for the l2ProtocolUpgradeTx. /// @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 evmEmulatorHash The hash of the new EVM emulator bytecode. If zero, it will not be updated. /// @param verifier The address of the new verifier. If zero, the verifier will not be updated. /// @param verifierParams The new verifier params. If all of its fields are 0, the params will not be updated. /// @param l1ContractsUpgradeCalldata Custom calldata for L1 contracts upgrade, it may be interpreted differently @@ -134,14 +133,16 @@ abstract contract BaseZkSyncUpgrade is ZkSyncHyperchainBase { return; } - require(!_patchOnly, "Patch only upgrade can not set new EVM emulator"); + if (_patchOnly) { + revert PatchUpgradeCantSetEvmEmulator(); + } L2ContractHelper.validateBytecodeHash(_l2EvmEmulatorBytecodeHash); // Save previous value into the stack to put it into the event later bytes32 previousL2EvmEmulatorBytecodeHash = s.l2EvmEmulatorBytecodeHash; - // Change the default account bytecode hash + // Change the EVM emulator bytecode hash s.l2EvmEmulatorBytecodeHash = _l2EvmEmulatorBytecodeHash; emit NewL2EvmEmulatorBytecodeHash(previousL2EvmEmulatorBytecodeHash, _l2EvmEmulatorBytecodeHash); } diff --git a/l1-contracts/contracts/upgrades/ZkSyncUpgradeErrors.sol b/l1-contracts/contracts/upgrades/ZkSyncUpgradeErrors.sol index b30c882e7..fe39d7844 100644 --- a/l1-contracts/contracts/upgrades/ZkSyncUpgradeErrors.sol +++ b/l1-contracts/contracts/upgrades/ZkSyncUpgradeErrors.sol @@ -32,6 +32,8 @@ error ProtocolVersionShouldBeGreater(uint256 _oldProtocolVersion, uint256 _newPr error PatchUpgradeCantSetDefaultAccount(); // 0x962fd7d0 error PatchUpgradeCantSetBootloader(); +// 0xc231eccd +error PatchUpgradeCantSetEvmEmulator(); // 0x101ba748 error PreviousUpgradeNotFinalized(bytes32 txHash); // 0xa0f47245 diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index cc383827e..7f1decf11 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": "0x010005db2681b1835b7de4cca51ae5dd08b63ab5fd37c990e359070221fba2f4", - "sourceCodeHash": "0x834845a85ef7426c763c783dfc56ed994d3015f8ea8a6fdc5c686c0cc279d002" + "bytecodeHash": "0x010005dbf9cf3db6804c31e55e9a496ab13894510e3c206cf4889e0fbd05db0c", + "sourceCodeHash": "0xb6dff8c2119b2a890fab54c773b3a7115dcd6ec721e87396a82a3491f8645d2b" }, { "contractName": "Create2Factory", diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index e52260e8c..9cf933753 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -1,7 +1,5 @@ // SPDX-License-Identifier: MIT -// solhint-disable reason-string, gas-custom-errors, func-named-parameters - pragma solidity 0.8.24; import {ImmutableData} from "./interfaces/IImmutableSimulator.sol"; From 2dfa07d564367b1016a45fd386a42c2d30da3837 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 23 Oct 2024 20:00:22 +0200 Subject: [PATCH 088/183] fix(EVM): Optional EVM support during chain creation (#969) --- .../StateTransitionManager.sol | 34 +++++++++---- .../l2-deps/AllowedBytecodeTypes.sol | 11 +++++ .../l2-deps/ISystemContext.sol | 7 ++- .../PrepareZKChainRegistrationCalldata.s.sol | 12 ++++- .../deploy-scripts/RegisterHyperchain.s.sol | 11 ++++- l1-contracts/scripts/register-hyperchain.ts | 17 ++++++- l1-contracts/src.ts/deploy-process.ts | 6 ++- l1-contracts/src.ts/deploy.ts | 13 +++-- .../Bridgehub/experimental_bridge.t.sol | 15 ++++-- .../Governance/PermanentRestriction.t.sol | 4 +- .../CreateNewChain.t.sol | 13 ++++- .../_StateTransitionManager_Shared.t.sol | 23 ++++++++- system-contracts/SystemContractsHashes.json | 34 ++++++------- .../contracts/ContractDeployer.sol | 49 +++++++++++-------- system-contracts/contracts/SystemContext.sol | 13 ++++- .../interfaces/IContractDeployer.sol | 4 ++ system-contracts/foundry.toml | 7 ++- .../test/ContractDeployer.spec.ts | 17 +++++-- 18 files changed, 220 insertions(+), 70 deletions(-) create mode 100644 l1-contracts/contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol diff --git a/l1-contracts/contracts/state-transition/StateTransitionManager.sol b/l1-contracts/contracts/state-transition/StateTransitionManager.sol index a14298f2a..f610bad78 100644 --- a/l1-contracts/contracts/state-transition/StateTransitionManager.sol +++ b/l1-contracts/contracts/state-transition/StateTransitionManager.sol @@ -13,6 +13,7 @@ import {IDiamondInit} from "./chain-interfaces/IDiamondInit.sol"; import {IExecutor} from "./chain-interfaces/IExecutor.sol"; import {IStateTransitionManager, StateTransitionManagerInitializeData, ChainCreationParams} from "./IStateTransitionManager.sol"; import {ISystemContext} from "./l2-deps/ISystemContext.sol"; +import {AllowedBytecodeTypes} from "./l2-deps/AllowedBytecodeTypes.sol"; import {IZkSyncHyperchain} from "./chain-interfaces/IZkSyncHyperchain.sol"; import {FeeParams} from "./chain-deps/ZkSyncHyperchainStorage.sol"; import {L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR, L2_FORCE_DEPLOYER_ADDR} from "../common/L2ContractAddresses.sol"; @@ -322,8 +323,15 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own /// registration /// @dev we have to set the chainId at genesis, as blockhashzero is the same for all chains with the same chainId - function _setChainIdUpgrade(uint256 _chainId, address _chainContract) internal { - bytes memory systemContextCalldata = abi.encodeCall(ISystemContext.setChainId, (_chainId)); + function _setChainConfigurationUpgrade( + uint256 _chainId, + AllowedBytecodeTypes _allowedBytecodeTypesMode, + address _chainContract + ) internal { + bytes memory systemContextCalldata = abi.encodeCall( + ISystemContext.setChainConfiguration, + (_chainId, uint256(_allowedBytecodeTypesMode)) + ); uint256[] memory uintEmptyArray; bytes[] memory bytesEmptyArray; @@ -396,13 +404,13 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own /// @param _baseToken the base token address used to pay for gas fees /// @param _sharedBridge the shared bridge address, used as base token bridge /// @param _admin the chain's admin address - /// @param _diamondCut the diamond cut data that initializes the chains Diamond Proxy + /// @param _inputData the input data for chain creation function createNewChain( uint256 _chainId, address _baseToken, address _sharedBridge, address _admin, - bytes calldata _diamondCut + bytes calldata _inputData ) external onlyBridgehub { if (getHyperchain(_chainId) != address(0)) { // Hyperchain already registered @@ -410,12 +418,18 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own } // check not registered + (bytes memory _diamondCut, AllowedBytecodeTypes allowedBytecodeTypesMode) = abi.decode( + _inputData, + (bytes, AllowedBytecodeTypes) + ); Diamond.DiamondCutData memory diamondCut = abi.decode(_diamondCut, (Diamond.DiamondCutData)); - // check input - bytes32 cutHashInput = keccak256(_diamondCut); - if (cutHashInput != initialCutHash) { - revert HashMismatch(initialCutHash, cutHashInput); + { + // check input + bytes32 cutHashInput = keccak256(_diamondCut); + if (cutHashInput != initialCutHash) { + revert HashMismatch(initialCutHash, cutHashInput); + } } // construct init data @@ -445,8 +459,8 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own _registerNewHyperchain(_chainId, hyperchainAddress); - // set chainId in VM - _setChainIdUpgrade(_chainId, hyperchainAddress); + // set chain configuration: chainId in VM and allowed bytecode types + _setChainConfigurationUpgrade(_chainId, allowedBytecodeTypesMode, hyperchainAddress); } /// @dev This internal function is used to register a new hyperchain in the system. diff --git a/l1-contracts/contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol b/l1-contracts/contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol new file mode 100644 index 000000000..2d6a3a136 --- /dev/null +++ b/l1-contracts/contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +// 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.21; + +/// @notice Defines what types of bytecode are allowed to be deployed on this chain +/// - `EraVm` means that only native contracts can be deployed +/// - `EraVmAndEVM` means that native contracts and EVM contracts can be deployed +enum AllowedBytecodeTypes { + EraVm, + EraVmAndEVM +} diff --git a/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.sol b/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.sol index d3244b74b..ea224aa3f 100644 --- a/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.sol +++ b/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.sol @@ -2,6 +2,11 @@ // 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.21; +import {AllowedBytecodeTypes} from "./AllowedBytecodeTypes.sol"; + interface ISystemContext { - function setChainId(uint256 _newChainId) external; + /// @notice Set the chain configuration. + /// @param _newChainId The chainId + /// @param _newAllowedBytecodeTypes The new allowed bytecode types mode. + function setChainConfiguration(uint256 _newChainId, uint256 _newAllowedBytecodeTypes) external; } diff --git a/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol b/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol index 0a7e20a53..0e77cfe0d 100644 --- a/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol +++ b/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol @@ -12,6 +12,7 @@ import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol" import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; import {L1SharedBridge} from "contracts/bridge/L1SharedBridge.sol"; import {IStateTransitionManager} from "contracts/state-transition/IStateTransitionManager.sol"; +import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {IGovernance} from "contracts/governance/IGovernance.sol"; import {Utils} from "./Utils.sol"; @@ -74,6 +75,8 @@ contract PrepareZKChainRegistrationCalldataScript is Script { bytes diamondCutData; // Address of the L1 ERC20 bridge proxy (required for the L2 bridge deployment) address erc20BridgeProxy; + // Should be EVM emulator supported or not + bool allowEvmEmulator; } // Addresses of the contracts in the L1 ecosystem that are fetched from the chain @@ -151,6 +154,7 @@ contract PrepareZKChainRegistrationCalldataScript is Script { config.diamondCutData = toml.readBytes("$.chain.diamond_cut_data"); config.bridgehubCreateNewChainSalt = toml.readUint("$.chain.bridgehub_create_new_chain_salt"); config.baseToken = toml.readAddress("$.chain.base_token_addr"); + config.allowEvmEmulator = toml.readBool("$.chain.allow_evm_emulator"); bytecodes.l2SharedBridgeBytecode = Utils.readHardhatBytecode("/script-config/artifacts/L2SharedBridge.json"); bytecodes.beaconProxy = Utils.readHardhatBytecode("/script-config/artifacts/BeaconProxy.json"); @@ -270,6 +274,12 @@ contract PrepareZKChainRegistrationCalldataScript is Script { function prepareRegisterHyperchainCall() internal view returns (IGovernance.Call memory) { Bridgehub bridgehub = Bridgehub(ecosystem.bridgehub); + AllowedBytecodeTypes allowedBytecodeTypesMode = config.allowEvmEmulator + ? AllowedBytecodeTypes.EraVmAndEVM + : AllowedBytecodeTypes.EraVm; + + bytes memory diamondCutEncoded = abi.encode(config.diamondCutData); + bytes memory data = abi.encodeCall( bridgehub.createNewChain, ( @@ -278,7 +288,7 @@ contract PrepareZKChainRegistrationCalldataScript is Script { config.baseToken, config.bridgehubCreateNewChainSalt, config.chainAdmin, - config.diamondCutData + abi.encode(diamondCutEncoded, allowedBytecodeTypesMode) ) ); diff --git a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol index 94acb2f02..a10d71b1f 100644 --- a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol +++ b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol @@ -10,6 +10,7 @@ import {stdToml} from "forge-std/StdToml.sol"; import {Ownable} from "@openzeppelin/contracts-v4/access/Ownable.sol"; import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol"; +import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol"; import {Governance} from "contracts/governance/Governance.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; @@ -44,6 +45,7 @@ contract RegisterHyperchainScript is Script { address newDiamondProxy; address governance; address chainAdmin; + bool allowEvmEmulator; } Config internal config; @@ -100,6 +102,7 @@ contract RegisterHyperchainScript is Script { ); config.governanceMinDelay = uint256(toml.readUint("$.chain.governance_min_delay")); config.governanceSecurityCouncilAddress = toml.readAddress("$.chain.governance_security_council_address"); + config.allowEvmEmulator = toml.readBool("$.chain.allow_evm_emulator"); } function checkTokenAddress() internal view { @@ -166,6 +169,12 @@ contract RegisterHyperchainScript is Script { IBridgehub bridgehub = IBridgehub(config.bridgehub); Ownable ownable = Ownable(config.bridgehub); + AllowedBytecodeTypes allowedBytecodeTypesMode = config.allowEvmEmulator + ? AllowedBytecodeTypes.EraVmAndEVM + : AllowedBytecodeTypes.EraVm; + + bytes memory diamondCutEncoded = abi.encode(config.diamondCutData); + vm.recordLogs(); bytes memory data = abi.encodeCall( bridgehub.createNewChain, @@ -175,7 +184,7 @@ contract RegisterHyperchainScript is Script { config.baseToken, config.bridgehubCreateNewChainSalt, msg.sender, - config.diamondCutData + abi.encode(diamondCutEncoded, allowedBytecodeTypesMode) ) ); diff --git a/l1-contracts/scripts/register-hyperchain.ts b/l1-contracts/scripts/register-hyperchain.ts index 1c60ad58d..587edec2e 100644 --- a/l1-contracts/scripts/register-hyperchain.ts +++ b/l1-contracts/scripts/register-hyperchain.ts @@ -68,6 +68,7 @@ async function main() { .option("--base-token-address ") .option("--use-governance ") .option("--token-multiplier-setter-address ") + .option("--allow-evm-emulation") .action(async (cmd) => { const deployWallet = cmd.privateKey ? new Wallet(cmd.privateKey, provider) @@ -106,7 +107,21 @@ async function main() { const tokenMultiplierSetterAddress = cmd.tokenMultiplierSetterAddress || ""; - await deployer.registerHyperchain(baseTokenAddress, cmd.validiumMode, null, gasPrice, useGovernance); + const isEvmEmulatorSupported = !!cmd.allowEvmEmulation; + + console.log(`EVM emulator: ${isEvmEmulatorSupported ? "SUPPORTED" : " NOT SUPPORTED"}`); + + await deployer.registerHyperchain( + baseTokenAddress, + cmd.validiumMode, + null, + gasPrice, + null, + null, + null, + useGovernance, + isEvmEmulatorSupported + ); if (tokenMultiplierSetterAddress != "") { console.log(`Using token multiplier setter address: ${tokenMultiplierSetterAddress}`); await deployer.setTokenMultiplierSetterAddress(tokenMultiplierSetterAddress); diff --git a/l1-contracts/src.ts/deploy-process.ts b/l1-contracts/src.ts/deploy-process.ts index e9622bfbe..1e1a00be2 100644 --- a/l1-contracts/src.ts/deploy-process.ts +++ b/l1-contracts/src.ts/deploy-process.ts @@ -80,7 +80,8 @@ export async function registerHyperchain( gasPrice: BigNumberish, baseTokenName?: string, chainId?: string, - useGovernance: boolean = false + useGovernance: boolean = false, + isEvmEmulatorSupported: boolean = false ) { const testnetTokens = getTokens(); @@ -99,6 +100,7 @@ export async function registerHyperchain( false, null, chainId, - useGovernance + useGovernance, + isEvmEmulatorSupported ); } diff --git a/l1-contracts/src.ts/deploy.ts b/l1-contracts/src.ts/deploy.ts index 0075b676c..d7ba372e4 100644 --- a/l1-contracts/src.ts/deploy.ts +++ b/l1-contracts/src.ts/deploy.ts @@ -744,7 +744,8 @@ export class Deployer { compareDiamondCutHash: boolean = false, nonce?, predefinedChainId?: string, - useGovernance: boolean = false + useGovernance: boolean = false, + isEvmEmulatorSupported: boolean = false ) { const gasLimit = 10_000_000; @@ -756,7 +757,13 @@ export class Deployer { const inputChainId = predefinedChainId || getNumberFromEnv("CHAIN_ETH_ZKSYNC_NETWORK_ID"); const admin = process.env.CHAIN_ADMIN_ADDRESS || this.ownerAddress; const diamondCutData = await this.initialZkSyncHyperchainDiamondCut(extraFacets, compareDiamondCutHash); - const initialDiamondCut = new ethers.utils.AbiCoder().encode([DIAMOND_CUT_DATA_ABI_STRING], [diamondCutData]); + const diamondCutDataEncoded = new ethers.utils.AbiCoder().encode([DIAMOND_CUT_DATA_ABI_STRING], [diamondCutData]); + + const allowedBytecodeTypesMode = isEvmEmulatorSupported ? 1 : 0; + const initData = new ethers.utils.AbiCoder().encode( + ["bytes", "uint256"], + [diamondCutDataEncoded, allowedBytecodeTypesMode] + ); const receipt = await this.executeDirectOrGovernance( useGovernance, @@ -768,7 +775,7 @@ export class Deployer { baseTokenAddress, Date.now(), admin, - initialDiamondCut, + initData, ], 0, { diff --git a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol index 910350041..ec90f0d66 100644 --- a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol @@ -8,6 +8,7 @@ import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; import {TestnetERC20Token} from "contracts/dev-contracts/TestnetERC20Token.sol"; import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {ChainCreationParams} from "contracts/state-transition/IStateTransitionManager.sol"; +import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {L2TransactionRequestDirect, L2TransactionRequestTwoBridgesOuter} from "contracts/bridgehub/IBridgehub.sol"; import {DummyStateTransitionManagerWBH} from "contracts/dev-contracts/test/DummyStateTransitionManagerWithBridgeHubAddress.sol"; import {DummyHyperchain} from "contracts/dev-contracts/test/DummyHyperchain.sol"; @@ -665,7 +666,8 @@ contract ExperimentalBridgeTest is Test { isFreezable, mockSelectors, mockInitAddress, - mockInitCalldata + mockInitCalldata, + false ); // bridgeHub.createNewChain => stateTransitionManager.createNewChain => this function sets the stateTransition mapping @@ -1435,7 +1437,8 @@ contract ExperimentalBridgeTest is Test { bool isFreezable, bytes4[] memory mockSelectors, address, //mockInitAddress, - bytes memory //mockInitCalldata + bytes memory, //mockInitCalldata + bool allowEvmEmulation ) internal returns (bytes memory) { bytes4[] memory singleSelector = new bytes4[](1); singleSelector[0] = bytes4(0xabcdef12); @@ -1469,7 +1472,13 @@ contract ExperimentalBridgeTest is Test { mockSTM.setChainCreationParams(params); - return abi.encode(diamondCutData); + bytes memory diamondCutEncoded = abi.encode(diamondCutData); + + AllowedBytecodeTypes allowedBytecodeTypesMode = allowEvmEmulation + ? AllowedBytecodeTypes.EraVmAndEVM + : AllowedBytecodeTypes.EraVm; + + return abi.encode(diamondCutEncoded, allowedBytecodeTypesMode); } function _setUpHyperchainForChainId(uint256 mockChainId) internal returns (uint256 mockChainIdInRange) { diff --git a/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol index 0e9dc0bce..33858b38f 100644 --- a/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol @@ -10,6 +10,7 @@ import {IPermanentRestriction} from "contracts/governance/IPermanentRestriction. import {ZeroAddress, ChainZeroAddress, NotAnAdmin, UnallowedImplementation, RemovingPermanentRestriction, CallNotAllowed} from "contracts/common/L1ContractErrors.sol"; import {Call} from "contracts/governance/Common.sol"; import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol"; +import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {VerifierParams, FeeParams, PubdataPricingMode} from "contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol"; import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; @@ -197,13 +198,14 @@ contract PermanentRestrictionTest is StateTransitionManagerTest { bridgehub.addStateTransitionManager(address(chainContractAddress)); bridgehub.addToken(baseToken); bridgehub.setSharedBridge(sharedBridge); + bridgehub.createNewChain({ _chainId: chainId, _stateTransitionManager: address(chainContractAddress), _baseToken: baseToken, _salt: 0, _admin: newChainAdmin, - _initData: abi.encode(_diamondCut) + _initData: getCreateInputData(_diamondCut, false) }); } } diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol index 0598779a4..48cbb95b2 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.24; import {StateTransitionManagerTest} from "./_StateTransitionManager_Shared.t.sol"; import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; +import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {Unauthorized, HashMismatch} from "contracts/common/L1ContractErrors.sol"; contract createNewChainTest is StateTransitionManagerTest { @@ -33,7 +34,7 @@ contract createNewChainTest is StateTransitionManagerTest { _baseToken: baseToken, _sharedBridge: sharedBridge, _admin: admin, - _diamondCut: abi.encode(initialDiamondCutData) + _inputData: getCreateInputData(initialDiamondCutData, false) }); } @@ -46,4 +47,14 @@ contract createNewChainTest is StateTransitionManagerTest { assertEq(newChainAdmin, admin); assertNotEq(newChainAddress, address(0)); } + + function test_SuccessfulCreationOfNewChainWithEvmEmulator() public { + createNewChainWithEvmEmulator(getDiamondCutData(diamondInit)); + + address admin = chainContractAddress.getChainAdmin(chainId); + address newChainAddress = chainContractAddress.getHyperchain(chainId); + + assertEq(newChainAdmin, admin); + assertNotEq(newChainAddress, address(0)); + } } diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol index 918cfa476..b13b1f920 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol @@ -17,6 +17,7 @@ import {DiamondInit} from "contracts/state-transition/chain-deps/DiamondInit.sol import {GenesisUpgrade} from "contracts/upgrades/GenesisUpgrade.sol"; import {InitializeDataNewChain} from "contracts/state-transition/chain-interfaces/IDiamondInit.sol"; import {StateTransitionManager} from "contracts/state-transition/StateTransitionManager.sol"; +import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {StateTransitionManagerInitializeData, ChainCreationParams} from "contracts/state-transition/IStateTransitionManager.sol"; import {TestnetVerifier} from "contracts/state-transition/TestnetVerifier.sol"; import {ZeroAddress} from "contracts/common/L1ContractErrors.sol"; @@ -128,7 +129,27 @@ contract StateTransitionManagerTest is Test { return Diamond.DiamondCutData({facetCuts: facetCuts, initAddress: _diamondInit, initCalldata: initCalldata}); } + function getCreateInputData( + Diamond.DiamondCutData memory _diamondCut, + bool allowEvmEmulator + ) internal view returns (bytes memory) { + bytes memory diamondCutEncoded = abi.encode(_diamondCut); + AllowedBytecodeTypes allowedBytecodeTypesMode = allowEvmEmulator + ? AllowedBytecodeTypes.EraVmAndEVM + : AllowedBytecodeTypes.EraVm; + + return abi.encode(diamondCutEncoded, allowedBytecodeTypesMode); + } + function createNewChain(Diamond.DiamondCutData memory _diamondCut) internal { + _createNewChain(_diamondCut, false); + } + + function createNewChainWithEvmEmulator(Diamond.DiamondCutData memory _diamondCut) internal { + _createNewChain(_diamondCut, true); + } + + function _createNewChain(Diamond.DiamondCutData memory _diamondCut, bool allowEvmEmulator) private { vm.stopPrank(); vm.startPrank(address(bridgehub)); @@ -137,7 +158,7 @@ contract StateTransitionManagerTest is Test { _baseToken: baseToken, _sharedBridge: sharedBridge, _admin: newChainAdmin, - _diamondCut: abi.encode(_diamondCut) + _inputData: getCreateInputData(_diamondCut, allowEvmEmulator) }); } diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 7f1decf11..5cd059f95 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": "0x01000077028e51aec3a82c209b999e201eb877e8269962246b85008b9de1c021", + "bytecodeHash": "0x010000779387ba87caebefbef966dc263054f8950a3120e6c3605445a215429c", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f134d6b56f5bb2917ab70bdf76126b271242f73b794453d6b912144a87", + "bytecodeHash": "0x010006f12f4e0198d02d5aaa39395041ffa928cabe89341d9e05ac9f2eb6b5fb", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x010000479bc5a91bc0579990aa4d021696050b245fd3345e4e53e60b64138ee2", + "bytecodeHash": "0x01000047ae25b732df64265d8fdb4935aa05b26448c35376e55d450cecafa09a", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013f862bf8b79fa219aeadcb67880bc97b6648cfe157733922e174cccca4", + "bytecodeHash": "0x0100013f4563482d39692847cc181b307598310ae4f1e8200c5cb607d64540e0", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010005dbf9cf3db6804c31e55e9a496ab13894510e3c206cf4889e0fbd05db0c", - "sourceCodeHash": "0xb6dff8c2119b2a890fab54c773b3a7115dcd6ec721e87396a82a3491f8645d2b" + "bytecodeHash": "0x010005d96d65df3e365c610e98b2b1e891b0a9171ccd79672c925754a1916bfb", + "sourceCodeHash": "0x7b99c6e8362654f9242079f1b664fe540ac3460547b773649f3e104c79b181a2" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003fd3dcd14aa3d6ccae73e6e559d8e127cab59edc880728740e3a4e2f61", + "bytecodeHash": "0x0100003f7dffcaa5e1013247a5da647824751cea975531af39b5aa8a1ceb04b6", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x01000503a1205f3d5eacfb84fae1746fca2f326870cecdc7d96471d90a08f472", + "bytecodeHash": "0x0100050368138aaf52ed6bce4e180805eb72b4aaab97fd6fffa038cb457b62f1", "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" }, { @@ -59,57 +59,57 @@ "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033d4ca4f62a4216a848300c3277afb6fe332c2d1d0e52217df01a3609c", + "bytecodeHash": "0x01000033c30d3d524b93a943e8dd7dba3d096730c12d5b3bb52311c55f812eed", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000c1790b5f0a79505c94fae292748850690e0569b27dba3de95899d8de1e", + "bytecodeHash": "0x010000c1f7b2fefcf367b8c3a52debb615512bec8c9f768d2f18a3e864a4db6a", "sourceCodeHash": "0xeb83e3a2ea2f50b93122363b8dd56fbcfe821d11723d849eecbde3d6af1147de" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x0100026586b7819633ded9a96621293986d59d63328457b9a33caba9018dc857", + "bytecodeHash": "0x010002656691523f71be5e405f3ee49da893d16ce72787d5eeda7bd10c30bcb8", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f307578eb3a57c2373e597fff622c6b4b15d76ed730f445e51a73f6fa4", + "bytecodeHash": "0x010000f3a6bb6fc63f2beefcfea0a33bade2cd6d943c78b8cc540126e6c89564", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x01000059376102d591ee9804ef9e0e6557c9b1fa231dced5635f87966e69a252", + "bytecodeHash": "0x010000598d4353beeea44dccfede2563de16f446c19c7ba7a417170ce353b295", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cf6479ebeb83e1ab27fcf3cbf7d04b9afa02357a9c88485c93076e2589", + "bytecodeHash": "0x010000cf091013c3fec019ce0ac2f3b54a578b2d8b9ff92bb708e4f6bbb4afa9", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041a140ce3229704f5d7b25181dcc3df3a16d4f52f9d794bc964aef8d17", + "bytecodeHash": "0x01000041b2cad46dfa6de19275af9f1e87924f8d03c5f1a9d8b8349d521d55c1", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a5ca16a30d14b5b2bc67173b8d30b728d6e79a3ae142925c3af3cd3019", - "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" + "bytecodeHash": "0x010001c5cf3b0a9b74992e48334f871f44d88205077933f932193367ee6fd259", + "sourceCodeHash": "0xc5ce25a94e3b510183635dd2fe0152dbcaa705bc8802fb3a4390253b5af3aa0a" }, { "contractName": "EventWriter", diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 9cf933753..7199cd379 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; 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_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, SYSTEM_CONTEXT_CONTRACT} from "./Constants.sol"; import {Utils} from "./libraries/Utils.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; @@ -37,26 +37,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _; } - /// @notice Can be used only during upgrades. - /// @param newAllowedBytecodeTypes The new allowed bytecode types mode. - /// @dev Changes what types of bytecodes are allowed to be deployed on the chain. - constructor(uint256 newAllowedBytecodeTypes) { - if ( - newAllowedBytecodeTypes != uint256(AllowedBytecodeTypes.EraVm) && - newAllowedBytecodeTypes != uint256(AllowedBytecodeTypes.EraVmAndEVM) - ) { - revert InvalidAllowedBytecodeTypesMode(); - } - - if (uint256(_getAllowedBytecodeTypesMode()) != newAllowedBytecodeTypes) { - assembly { - sstore(ALLOWED_BYTECODE_TYPES_MODE_SLOT, newAllowedBytecodeTypes) - } - - emit AllowedBytecodeTypesModeUpdated(AllowedBytecodeTypes(newAllowedBytecodeTypes)); - } - } - function evmCodeHash(address _address) external view returns (bytes32 _hash) { _hash = _getEvmCodeHash(_address); } @@ -333,6 +313,33 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } } + /// @notice Changes what types of bytecodes are allowed to be deployed on the chain. Can be used only during upgrades. + /// @param newAllowedBytecodeTypes The new allowed bytecode types mode. + function setAllowedBytecodeTypesToDeploy(uint256 newAllowedBytecodeTypes) external { + if ( + msg.sender != FORCE_DEPLOYER && + msg.sender != address(COMPLEX_UPGRADER_CONTRACT) && + msg.sender != address(SYSTEM_CONTEXT_CONTRACT) + ) { + revert Unauthorized(msg.sender); + } + + if ( + newAllowedBytecodeTypes != uint256(AllowedBytecodeTypes.EraVm) && + newAllowedBytecodeTypes != uint256(AllowedBytecodeTypes.EraVmAndEVM) + ) { + revert InvalidAllowedBytecodeTypesMode(); + } + + if (uint256(_getAllowedBytecodeTypesMode()) != newAllowedBytecodeTypes) { + assembly { + sstore(ALLOWED_BYTECODE_TYPES_MODE_SLOT, newAllowedBytecodeTypes) + } + + emit AllowedBytecodeTypesModeUpdated(AllowedBytecodeTypes(newAllowedBytecodeTypes)); + } + } + function _nonSystemDeployOnAddress( bytes32 _bytecodeHash, address _newAddress, diff --git a/system-contracts/contracts/SystemContext.sol b/system-contracts/contracts/SystemContext.sol index 4763b4153..eab089e8f 100644 --- a/system-contracts/contracts/SystemContext.sol +++ b/system-contracts/contracts/SystemContext.sol @@ -8,7 +8,7 @@ import {ISystemContext} from "./interfaces/ISystemContext.sol"; import {SystemContractBase} from "./abstract/SystemContractBase.sol"; import {ISystemContextDeprecated} from "./interfaces/ISystemContextDeprecated.sol"; import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; -import {BOOTLOADER_FORMAL_ADDRESS, SystemLogKey} from "./Constants.sol"; +import {BOOTLOADER_FORMAL_ADDRESS, DEPLOYER_SYSTEM_CONTRACT, SystemLogKey} from "./Constants.sol"; /** * @author Matter Labs @@ -89,6 +89,17 @@ contract SystemContext is ISystemContext, ISystemContextDeprecated, SystemContra chainId = _newChainId; } + /// @notice Set the chain configuration. + /// @param _newChainId The chainId + /// @param _newAllowedBytecodeTypes The new allowed bytecode types mode. + function setChainConfiguration( + uint256 _newChainId, + uint256 _newAllowedBytecodeTypes + ) external onlyCallFromForceDeployer { + chainId = _newChainId; + DEPLOYER_SYSTEM_CONTRACT.setAllowedBytecodeTypesToDeploy(_newAllowedBytecodeTypes); + } + /// @notice Number of current transaction in block. uint16 public txNumberInBlock; diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index c4b090a58..ef8c83f95 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -109,4 +109,8 @@ interface IContractDeployer { function evmCodeHash(address) external view returns (bytes32); function constructorReturnGas() external view returns (uint256); + + /// @notice Changes what types of bytecodes are allowed to be deployed on the chain. Can be used only during upgrades. + /// @param newAllowedBytecodeTypes The new allowed bytecode types mode. + function setAllowedBytecodeTypesToDeploy(uint256 newAllowedBytecodeTypes) external; } diff --git a/system-contracts/foundry.toml b/system-contracts/foundry.toml index 748734ad6..a820faa90 100644 --- a/system-contracts/foundry.toml +++ b/system-contracts/foundry.toml @@ -3,11 +3,14 @@ src = "contracts-preprocessed" out = "out" libs = ["lib"] cache_path = "cache-forge" -evm_version = "paris" +evm_version = "cancun" +solc_version = "0.8.24" remappings = [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", ] +suppressedErrors = ["sendtransfer"] [profile.default.zksync] -zksolc = "1.5.4" +zksolc = "1.5.6" +suppressedErrors = ["sendtransfer"] diff --git a/system-contracts/test/ContractDeployer.spec.ts b/system-contracts/test/ContractDeployer.spec.ts index 569a9f9b5..df4603710 100644 --- a/system-contracts/test/ContractDeployer.spec.ts +++ b/system-contracts/test/ContractDeployer.spec.ts @@ -66,12 +66,21 @@ describe("ContractDeployer tests", function () { }); }); - describe("constructor", function () { + describe("setAllowedBytecodeTypesToDeploy", function () { + it("can't change if not forceDeployer", async () => { + const newContractDeployer = await deployContract("ContractDeployer", []); + + expect(newContractDeployer.setAllowedBytecodeTypesToDeploy(1)).to.be.revertedWithCustomError( + newContractDeployer, + "Unauthorized" + ); + }); + it("successfully updated allowedBytecodeTypesToDeploy", async () => { - const newContractDeployer = await deployContract("ContractDeployer", [ - "0x0000000000000000000000000000000000000000000000000000000000000001", - ]); + const newContractDeployer = await deployContract("ContractDeployer", []); + expect(await newContractDeployer.allowedBytecodeTypesToDeploy()).to.be.eq(0); + await newContractDeployer.connect(forceDeployer).setAllowedBytecodeTypesToDeploy(1); expect(await newContractDeployer.allowedBytecodeTypesToDeploy()).to.be.eq(1); }); }); From 51403268293bb9753488c0a54c9c9d4d406fa47e Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 24 Oct 2024 14:47:22 +0200 Subject: [PATCH 089/183] feat(EVM): Simplify warm/cold storage model for "small" slots (#971) --- system-contracts/SystemContractsHashes.json | 4 +-- system-contracts/contracts/EvmGasManager.yul | 33 +++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 5cd059f95..e4f34b7d0 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -129,8 +129,8 @@ "contractName": "EvmGasManager", "bytecodePath": "contracts-preprocessed/artifacts/EvmGasManager.yul/EvmGasManager.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmGasManager.yul", - "bytecodeHash": "0x0100005577ee81de6b5334d9f91ea8d9a91f02e3afa057bb0455f2e2d8aac636", - "sourceCodeHash": "0xd27ca9819fad1f1dc3fbc7f2c90f5ba2a9907413036fc78efbcee33649c975cb" + "bytecodeHash": "0x01000059d5a1736d5865f592c5dcf2e301697b83d4abfdc4a8fa2b5cfe88de8d", + "sourceCodeHash": "0xad51904bf2b8cd81cb66962c3211c9514e6ccd0c5bd30288d1f5697b29639fcb" }, { "contractName": "CodeOracle", diff --git a/system-contracts/contracts/EvmGasManager.yul b/system-contracts/contracts/EvmGasManager.yul index 957f574b7..07eac468f 100644 --- a/system-contracts/contracts/EvmGasManager.yul +++ b/system-contracts/contracts/EvmGasManager.yul @@ -46,6 +46,10 @@ object "EvmGasManager" { mask := sub(shl(160, 1), 1) } + function MAX_88_BIT_VALUE() -> value { + value := sub(shl(88, 1), 1) + } + function $llvm_AlwaysInline_llvm$__getRawSenderCodeHash() -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, caller()) @@ -125,10 +129,17 @@ object "EvmGasManager" { } case 1 { // function isSlotWarm(uint256 _slot) // If specified slot in the caller storage is warm, will return 32 bytes of unspecified data. - mstore(0, calldataload(1)) // load _slot - mstore(32, or(IS_SLOT_WARM_PREFIX(), caller())) // prefixed caller address - - let transientSlot := keccak256(0, 64) + let _slot := calldataload(1) // load _slot + let transientSlot + switch gt(_slot, MAX_88_BIT_VALUE()) + case 1 { + mstore(0, _slot) + mstore(32, or(IS_SLOT_WARM_PREFIX(), caller())) // prefixed caller address + transientSlot := keccak256(0, 64) + } + case 0 { + transientSlot := or(shl(160, _slot), caller()) + } if tload(transientSlot) { return(0x0, 0x20) @@ -139,10 +150,18 @@ object "EvmGasManager" { // Warm slot in caller storage, if needed. Will return original value of the slot if it is already warm. $llvm_AlwaysInline_llvm$_onlyEvmSystemCall() - mstore(0, calldataload(1)) // load _slot - mstore(32, or(IS_SLOT_WARM_PREFIX(), caller())) // prefixed caller address + let _slot := calldataload(1) // load _slot + let transientSlot + switch gt(_slot, MAX_88_BIT_VALUE()) + case 1 { + mstore(0, _slot) + mstore(32, or(IS_SLOT_WARM_PREFIX(), caller())) // prefixed caller address + transientSlot := keccak256(0, 64) + } + case 0 { + transientSlot := or(shl(160, _slot), caller()) + } - let transientSlot := keccak256(0, 64) let isWarm := tload(transientSlot) if isWarm { From c60db613c397a5fa053be29d221a28cb0974ac50 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 24 Oct 2024 15:59:16 +0200 Subject: [PATCH 090/183] chore(EVM): Cleanup in emulator (#972) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 2406 +++++++++-------- .../evm-emulator/EvmEmulator.template.yul | 4 +- .../EvmEmulatorFunctions.template.yul | 1106 ++++---- .../evm-emulator/EvmEmulatorLoop.template.yul | 16 +- 5 files changed, 1785 insertions(+), 1751 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index e4f34b7d0..f91e2152a 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000d55ae987dc71cd41cf33a45bec8127083a2b6d4822883f3dba6e93dec70", - "sourceCodeHash": "0x1b7b331c17f27268bf7ca841e0742393e4708f14ea33ad231f9c280ea895bccd" + "bytecodeHash": "0x01000d553d34b21e5609df63cce2b19a00a700d51acd7398d144b9a83d5ab163", + "sourceCodeHash": "0x59010ac2de66c76109c3d150439d09afae1f70a55a39ff2d14f5ac3b13e6ed10" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 911fa083d..266c1150f 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -48,6 +48,10 @@ object "EvmEmulator" { returnGas := chargeGas(gasToReturn, gasForCode) } + //////////////////////////////////////////////////////////////// + // CONSTANTS + //////////////////////////////////////////////////////////////// + function ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008002 } @@ -68,12 +72,8 @@ object "EvmEmulator" { addr := 0x0000000000000000000000000000000000008013 } - function DEBUG_SLOT_OFFSET() -> offset { - offset := mul(32, 32) // TODO cleanup - } - function LAST_RETURNDATA_SIZE_OFFSET() -> offset { - offset := add(DEBUG_SLOT_OFFSET(), mul(5, 32)) + offset := mul(32, 32) } function STACK_OFFSET() -> offset { @@ -84,10 +84,6 @@ object "EvmEmulator" { offset := add(STACK_OFFSET(), mul(1024, 32)) } - function INF_PASS_GAS() -> inf { - inf := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - } - function MAX_POSSIBLE_BYTECODE() -> max { max := 32000 } @@ -112,94 +108,75 @@ object "EvmEmulator" { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } - function $llvm_NoInline_llvm$_revert() { - revert(0, 0) + function INF_PASS_GAS() -> inf { + inf := 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) - } + // 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 } - 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)) - } + // From precompiles/CodeOracle + function DECOMMIT_COST_PER_WORD() -> cost { cost := 4 } - function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { - evmGasLeft := chargeGas(evmGas, 3) - let tempSp := sub(sp, mul(0x20, sub(position, 1))) + function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } + //////////////////////////////////////////////////////////////// + // GENERAL FUNCTIONS + //////////////////////////////////////////////////////////////// - mstore(sp, oldStackHead) - stackHead := mload(tempSp) - newSp := add(sp, 0x20) + function $llvm_NoInline_llvm$_revert() { + revert(0, 0) } - function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { - evmGasLeft := chargeGas(evmGas, 3) - let tempSp := sub(sp, mul(0x20, position)) - - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := mload(tempSp) - mstore(tempSp, oldStackHead) + function revertWithGas(evmGasLeft) { + mstore(0, evmGasLeft) + revert(0, 32) } - function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { - // We can not return any error here, because it would break compatibility - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) + function chargeGas(prevGas, toCharge) -> gasRemaining { + if lt(prevGas, toCharge) { + revertWithGas(0) } - a := oldStackHead - newSp := sub(sp, 0x20) - stackHead := mload(newSp) + gasRemaining := sub(prevGas, toCharge) } - function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { - if iszero(lt(sp, BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) + function checkMemOverflowByOffset(offset, evmGasLeft) { + if gt(offset, MAX_POSSIBLE_MEM()) { + mstore(0, evmGasLeft) + revert(0, 32) } - - mstore(sp, oldStackHead) - stackHead := item - newSp := add(sp, 0x20) } - function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { - a := oldStackHead - newSp := sub(sp, 0x20) - stackHead := mload(newSp) + function checkMemOverflow(location, evmGasLeft) { + if gt(location, MAX_MEMORY_FRAME()) { + mstore(0, evmGasLeft) + revert(0, 32) + } } - function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { - mstore(sp, oldStackHead) - stackHead := item - newSp := add(sp, 0x20) + function checkOverflow(data1, data2, evmGasLeft) { + if lt(add(data1, data2), data2) { + revertWithGas(evmGasLeft) + } } - function popStackCheck(sp, evmGasLeft, numInputs) { - if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { - revertWithGas(evmGasLeft) + // 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 pushStackCheck(sp, evmGasLeft, numInputs) { - if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) + 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 getCodeAddress() -> addr { @@ -230,6 +207,35 @@ object "EvmEmulator" { verbatim_1i_0o("active_ptr_shrink_assign", _dest) } + function getIsStaticFromCallFlags() -> isStatic { + isStatic := verbatim_0i_1o("get_global::call_flags") + isStatic := iszero(iszero(and(isStatic, 0x04))) + } + + 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 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 _getRawCodeHash(account) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) @@ -244,11 +250,6 @@ object "EvmEmulator" { 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) @@ -311,32 +312,6 @@ object "EvmEmulator" { mstore(BYTECODE_OFFSET(), codeLen) } - function consumeEvmFrame() -> passGas, isStatic, callerEVM { - // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) - // non-standard selector 0x04 - mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) - - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) - - let _returndatasize := returndatasize() - if _returndatasize { - callerEVM := true - - returndatacopy(0, 0, 32) - passGas := mload(0) - - isStatic := gt(_returndatasize, 32) - } - } - - 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) { @@ -358,162 +333,11 @@ object "EvmEmulator" { 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 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()) + // 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 @@ -530,38 +354,6 @@ object "EvmEmulator" { } } - function isSlotWarm(key) -> isWarm { - // non-standard selector 0x01 - mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) - mstore(1, key) - - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - if returndatasize() { - isWarm := true - } - } - - function warmSlot(key,currentValue) -> isWarm, originalValue { - // non-standard selector 0x02 - mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) - mstore(1, key) - mstore(33,currentValue) - - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) - - if returndatasize() { - isWarm := true - returndatacopy(0, 0, 32) - originalValue := mload(0) - } - } - function performSystemCall( to, dataLength, @@ -583,55 +375,8 @@ object "EvmEmulator" { } } - - 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 { - // function warmAccount(address account) - // non-standard selector 0x00 - // addr is packed in the same word with selector - mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) - - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32) - - if returndatasize() { - isWarm := true - } - } - - 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) @@ -645,31 +390,13 @@ object "EvmEmulator" { isEVM := mload(0) } - function _pushEVMFrame(_passGas, _isStatic) { - // function pushEVMFrame - // non-standard selector 0x03 - mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) - mstore(32, _passGas) - - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) - } - - // 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 { + function zkVmGasToEvmGas(_zkevmGas) -> calczkevmGas { calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) // TODO round up } - function getEVMGas() -> evmGas { + function getEvmGasFromContext() -> evmGas { let _gas := gas() - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) // TODO CHECK GAS MECHANICS switch lt(_gas, requiredGas) case 1 { @@ -680,84 +407,160 @@ object "EvmEmulator" { } } - 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() + //////////////////////////////////////////////////////////////// + // STACK OPERATIONS + //////////////////////////////////////////////////////////////// + + function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, sub(position, 1))) + + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) } - } - function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft{ - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - let rtsz := returndatasize() + mstore(sp, oldStackHead) + stackHead := mload(tempSp) + newSp := add(sp, 0x20) + } - loadReturndataIntoActivePtr() + function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, position)) - // if (rtsz > 31) - switch gt(rtsz, 31) - case 0 { - // Unexpected return data. - _gasLeft := 0 - _eraseReturndataPointer() - } - default { - returndatacopy(0, 0, 32) - _gasLeft := mload(0) + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - // 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)) } + stackHead := mload(tempSp) + mstore(tempSp, oldStackHead) + } - mstore(lastRtSzOffset, sub(rtsz, 32)) + function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { + // We can not return any error here, because it would break compatibility + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - // Skip the returnData - ptrAddIntoActive(32) - } + a := oldStackHead + newSp := sub(sp, 0x20) + stackHead := mload(newSp) } - function _eraseReturndataPointer() { - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { + if iszero(lt(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } - let activePtrSize := getActivePtrDataSize() - ptrShrinkIntoActive(and(activePtrSize, 0xFFFFFFFF))// uint32(activePtrSize) - mstore(lastRtSzOffset, 0) + mstore(sp, oldStackHead) + stackHead := item + newSp := add(sp, 0x20) } - function _saveReturndataAfterZkEVMCall() { - loadReturndataIntoActivePtr() - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { + a := oldStackHead + newSp := sub(sp, 0x20) + stackHead := mload(newSp) + } - mstore(lastRtSzOffset, returndatasize()) + function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { + mstore(sp, oldStackHead) + stackHead := item + newSp := add(sp, 0x20) } - 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 popStackCheck(sp, evmGasLeft, numInputs) { + if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { + revertWithGas(evmGasLeft) } } - function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> maxExpand { - maxExpand := add(retOffset, retSize) - switch lt(maxExpand, add(argsOffset, argsSize)) - case 0 { - maxExpand := expandMemory(maxExpand) + function pushStackCheck(sp, evmGasLeft, numInputs) { + if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) } - default { - maxExpand := expandMemory(add(argsOffset, argsSize)) + } + + //////////////////////////////////////////////////////////////// + // EVM GAS MANAGER FUNCTIONALITY + //////////////////////////////////////////////////////////////// + + function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { + // function warmAccount(address account) + // non-standard selector 0x00 + // addr is packed in the same word with selector + mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) + + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32) + + if returndatasize() { + isWarm := true + } + } + + function isSlotWarm(key) -> isWarm { + // non-standard selector 0x01 + mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) + + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + if returndatasize() { + isWarm := true + } + } + + function warmSlot(key,currentValue) -> isWarm, originalValue { + // non-standard selector 0x02 + mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) + mstore(33,currentValue) + + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) + + if returndatasize() { + isWarm := true + returndatacopy(0, 0, 32) + originalValue := mload(0) + } + } + + function _pushEVMFrame(_passGas, _isStatic) { + // function pushEVMFrame + // non-standard selector 0x03 + mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) + mstore(32, _passGas) + + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) + } + + function consumeEvmFrame() -> passGas, isStatic, callerEVM { + // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) + // non-standard selector 0x04 + mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) + + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) + + let _returndatasize := returndatasize() + if _returndatasize { + callerEVM := true + + returndatacopy(0, 0, 32) + passGas := mload(0) + + isStatic := gt(_returndatasize, 32) } } + //////////////////////////////////////////////////////////////// + // CALLS FUNCTIONALITY + //////////////////////////////////////////////////////////////// + function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize @@ -800,13 +603,13 @@ object "EvmEmulator" { } { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGas(evmGasLeft, gasToPass) + gasToPass := capGasForCall(evmGasLeft, gasToPass) let success, frameGasLeft := _performCall( addr, @@ -858,13 +661,13 @@ object "EvmEmulator" { } { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGas(evmGasLeft, gasToPass) + gasToPass := capGasForCall(evmGasLeft, gasToPass) let success, frameGasLeft := _performStaticCall( addr, @@ -920,13 +723,13 @@ object "EvmEmulator" { } { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGas(evmGasLeft, gasToPass) + gasToPass := capGasForCall(evmGasLeft, gasToPass) _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( @@ -951,11 +754,11 @@ object "EvmEmulator" { switch _isEVM(addr) case 0 { // zkEVM native - let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) + let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() - let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) + let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) if gt(gasToPass, gasUsed) { frameGasLeft := sub(gasToPass, gasUsed) // TODO check @@ -972,11 +775,11 @@ object "EvmEmulator" { switch _isEVM(addr) case 0 { // zkEVM native - let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) + let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() - let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) + let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) if gt(gasToPass, gasUsed) { frameGasLeft := sub(gasToPass, gasUsed) // TODO check @@ -989,170 +792,300 @@ object "EvmEmulator" { } } - 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 _getZkEVMGasForCall(_evmGas, addr) -> zkevmGas { + // TODO CHECK COSTS CALCULATION + 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)) } - } - - 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) + let decommitGasCost := mul(div(byteSize,32), DECOMMIT_COST_PER_WORD()) + zkevmGas := sub(zkevmGas, decommitGasCost) + if gt(zkevmGas, UINT32_MAX()) { + zkevmGas := UINT32_MAX() } - - gasLeft := mload(0) } - function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { - _eraseReturndataPointer() - - let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) - - if lt(selfbalance(),value) { - revertWithGas(evmGasLeftOld) + function capGasForCall(evmGasLeft,oldGasToPass) -> gasToPass { + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + gasToPass := oldGasToPass + if gt(oldGasToPass, maxGasToPass) { + gasToPass := maxGasToPass } + } - offset := add(MEM_OFFSET_INNER(), offset) - - pushStackCheck(sp, evmGasLeftOld, 4) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) - - _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 getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) -> maxExpand { + maxExpand := add(retOffset, retSize) + switch lt(maxExpand, add(argsOffset, argsSize)) + case 0 { + maxExpand := expandMemory(maxExpand) } - - - 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) + default { + maxExpand := expandMemory(add(argsOffset, argsSize)) } + } - addr := mload(0) - - let gasLeft - switch result - case 0 { - gasLeft := _saveReturndataAfterEVMCall(0, 0) + // 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 } - default { - gasLeft := _fetchConstructorReturnGas() + 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 gasUsed := sub(gasForTheCall, gasLeft) - evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - - let back - - // skipping check since we pushed exactly 4 items earlier - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x20), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x40), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x60), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x80), back) - } + { + 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) + } + } - 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)) + // [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 $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) - } + function _saveReturndataAfterZkEVMCall() { + loadReturndataIntoActivePtr() + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - let rest_len := and(len, 31) - if rest_len { - $llvm_AlwaysInline_llvm$_copyRest(dest_addr, mload(src_addr), rest_len) - } + mstore(lastRtSzOffset, returndatasize()) } - 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) - } + function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft { + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + let rtsz := returndatasize() - let rest_len := and(len, 31) - if rest_len { - $llvm_AlwaysInline_llvm$_copyRest(dest_end, 0, rest_len) + 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) + } + + //////////////////////////////////////////////////////////////// + // CREATE FUNCTIONALITY + //////////////////////////////////////////////////////////////// + + 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 performExtCodeCopy(evmGas,oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { - evmGasLeft := chargeGas(evmGas, 100) + function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { + _eraseReturndataPointer() - let addr, dest, offset, len - popStackCheck(oldSp, evmGasLeft, 4) - addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + let gasForTheCall := capGasForCall(evmGasLeftOld,INF_PASS_GAS()) - // dynamicGas = 3 * minimum_word_size + memory_expansion_cost + address_access_cost - // minimum_word_size = (size + 31) / 32 + if lt(selfbalance(),value) { + revertWithGas(evmGasLeftOld) + } - 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) + offset := add(MEM_OFFSET_INNER(), offset) + + pushStackCheck(sp, evmGasLeftOld, 4) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) + + _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) } - 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()))) + 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) + + let back + + // skipping check since we pushed exactly 4 items earlier + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x20), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x40), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x60), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x80), back) } function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { @@ -1236,41 +1169,113 @@ object "EvmEmulator" { result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt, stackHead) } - - 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 stackHead - - 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) - - popStackCheck(sp, evmGasLeft, 2) - let a - a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - stackHead := add(a, stackHead) - + //////////////////////////////////////////////////////////////// + // EXTCODECOPY FUNCTIONALITY + //////////////////////////////////////////////////////////////// + + 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, oldStackHead) -> evmGasLeft, sp, stackHead { + evmGasLeft := chargeGas(evmGas, 100) + + let addr, dest, offset, len + popStackCheck(oldSp, evmGasLeft, 4) + addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + + // 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 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 stackHead + + 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) + + popStackCheck(sp, evmGasLeft, 2) + let a + a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + stackHead := add(a, stackHead) + ip := add(ip, 1) } case 0x02 { // OP_MUL @@ -2657,16 +2662,22 @@ object "EvmEmulator" { offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset,size, evmGasLeft) + checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) - evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) - + 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) - revert(offset,size) + if eq(isCallerEVM, 1) { + offset := sub(offset, 32) + size := add(size, 32) + + // include gas + mstore(offset, evmGasLeft) + } + + revert(offset, size) } case 0xFE { // OP_INVALID evmGasLeft := 0 @@ -3031,7 +3042,7 @@ object "EvmEmulator" { getConstructorBytecode() if iszero(isCallerEVM) { - evmGasLeft := getEVMGas() + evmGasLeft := getEvmGasFromContext() } let offset, len, gasToReturn := simulate(isCallerEVM, evmGasLeft, false) @@ -3046,6 +3057,10 @@ object "EvmEmulator" { } object "EvmEmulator_deployed" { code { + //////////////////////////////////////////////////////////////// + // CONSTANTS + //////////////////////////////////////////////////////////////// + function ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008002 } @@ -3066,12 +3081,8 @@ object "EvmEmulator" { addr := 0x0000000000000000000000000000000000008013 } - function DEBUG_SLOT_OFFSET() -> offset { - offset := mul(32, 32) // TODO cleanup - } - function LAST_RETURNDATA_SIZE_OFFSET() -> offset { - offset := add(DEBUG_SLOT_OFFSET(), mul(5, 32)) + offset := mul(32, 32) } function STACK_OFFSET() -> offset { @@ -3082,10 +3093,6 @@ object "EvmEmulator" { offset := add(STACK_OFFSET(), mul(1024, 32)) } - function INF_PASS_GAS() -> inf { - inf := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - } - function MAX_POSSIBLE_BYTECODE() -> max { max := 32000 } @@ -3110,94 +3117,75 @@ object "EvmEmulator" { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } - function $llvm_NoInline_llvm$_revert() { - revert(0, 0) + function INF_PASS_GAS() -> inf { + inf := 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) - } + // 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 } - 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)) - } + // From precompiles/CodeOracle + function DECOMMIT_COST_PER_WORD() -> cost { cost := 4 } - function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { - evmGasLeft := chargeGas(evmGas, 3) - let tempSp := sub(sp, mul(0x20, sub(position, 1))) + function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } + //////////////////////////////////////////////////////////////// + // GENERAL FUNCTIONS + //////////////////////////////////////////////////////////////// - mstore(sp, oldStackHead) - stackHead := mload(tempSp) - newSp := add(sp, 0x20) + function $llvm_NoInline_llvm$_revert() { + revert(0, 0) } - function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { - evmGasLeft := chargeGas(evmGas, 3) - let tempSp := sub(sp, mul(0x20, position)) - - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := mload(tempSp) - mstore(tempSp, oldStackHead) + function revertWithGas(evmGasLeft) { + mstore(0, evmGasLeft) + revert(0, 32) } - function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { - // We can not return any error here, because it would break compatibility - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) + function chargeGas(prevGas, toCharge) -> gasRemaining { + if lt(prevGas, toCharge) { + revertWithGas(0) } - a := oldStackHead - newSp := sub(sp, 0x20) - stackHead := mload(newSp) + gasRemaining := sub(prevGas, toCharge) } - function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { - if iszero(lt(sp, BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) + function checkMemOverflowByOffset(offset, evmGasLeft) { + if gt(offset, MAX_POSSIBLE_MEM()) { + mstore(0, evmGasLeft) + revert(0, 32) } - - mstore(sp, oldStackHead) - stackHead := item - newSp := add(sp, 0x20) } - function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { - a := oldStackHead - newSp := sub(sp, 0x20) - stackHead := mload(newSp) + function checkMemOverflow(location, evmGasLeft) { + if gt(location, MAX_MEMORY_FRAME()) { + mstore(0, evmGasLeft) + revert(0, 32) + } } - function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { - mstore(sp, oldStackHead) - stackHead := item - newSp := add(sp, 0x20) + function checkOverflow(data1, data2, evmGasLeft) { + if lt(add(data1, data2), data2) { + revertWithGas(evmGasLeft) + } } - function popStackCheck(sp, evmGasLeft, numInputs) { - if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { - revertWithGas(evmGasLeft) + // 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 pushStackCheck(sp, evmGasLeft, numInputs) { - if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) + 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 getCodeAddress() -> addr { @@ -3228,6 +3216,35 @@ object "EvmEmulator" { verbatim_1i_0o("active_ptr_shrink_assign", _dest) } + function getIsStaticFromCallFlags() -> isStatic { + isStatic := verbatim_0i_1o("get_global::call_flags") + isStatic := iszero(iszero(and(isStatic, 0x04))) + } + + 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 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 _getRawCodeHash(account) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) @@ -3242,11 +3259,6 @@ object "EvmEmulator" { 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) @@ -3280,232 +3292,55 @@ object "EvmEmulator" { 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, uint256 auxDataRes) - // non-standard selector 0x04 - mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) - - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) - - let _returndatasize := returndatasize() - if _returndatasize { - callerEVM := true - - returndatacopy(0, 0, 32) - passGas := mload(0) - - isStatic := gt(_returndatasize, 32) - } - } - - 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 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) + 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 checkMemOverflow(location, evmGasLeft) { - if gt(location, MAX_MEMORY_FRAME()) { - mstore(0, evmGasLeft) - revert(0, 32) + function getDeployedBytecode() { + let codeLen := _fetchDeployedCode( + getCodeAddress(), + add(BYTECODE_OFFSET(), 32), + MAX_POSSIBLE_BYTECODE() + ) + + mstore(BYTECODE_OFFSET(), codeLen) + } + + function getMax(a, b) -> max { + max := b + if gt(a, b) { + max := a } } - function checkOverflow(data1, data2, evmGasLeft) { - if lt(add(data1, data2), data2) { - revertWithGas(evmGasLeft) + 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 revertWithGas(evmGasLeft) { - mstore(0, evmGasLeft) - revert(0, 32) + function bitMaskFromBytes(nBytes) -> bitMask { + bitMask := sub(exp(2, mul(nBytes, 8)), 1) // 2**(nBytes*8) - 1 } // This function can overflow, it is the job of the caller to ensure that it does not. @@ -3528,38 +3363,6 @@ object "EvmEmulator" { } } - function isSlotWarm(key) -> isWarm { - // non-standard selector 0x01 - mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) - mstore(1, key) - - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - if returndatasize() { - isWarm := true - } - } - - function warmSlot(key,currentValue) -> isWarm, originalValue { - // non-standard selector 0x02 - mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) - mstore(1, key) - mstore(33,currentValue) - - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) - - if returndatasize() { - isWarm := true - returndatacopy(0, 0, 32) - originalValue := mload(0) - } - } - function performSystemCall( to, dataLength, @@ -3581,181 +3384,192 @@ object "EvmEmulator" { } } + function _isEVM(_addr) -> isEVM { + // function isAccountEVM(address _addr) external view returns (bool); + mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) + mstore(4, _addr) - 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 + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) - newOffset := sub(offset, 32) - newSize := add(size, 32) + if iszero(success) { + // This error should never happen + revert(0, 0) } + + isEVM := mload(0) } - function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { - // function warmAccount(address account) - // non-standard selector 0x00 - // addr is packed in the same word with selector - mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) + function zkVmGasToEvmGas(_zkevmGas) -> calczkevmGas { + calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) // TODO round up + } - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32) + function getEvmGasFromContext() -> evmGas { + let _gas := gas() + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) // TODO CHECK GAS MECHANICS - if returndatasize() { - isWarm := true + switch lt(_gas, requiredGas) + case 1 { + evmGas := 0 + } + default { + evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) } } - function getRawNonce(addr) -> nonce { - mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) - mstore(4, addr) + //////////////////////////////////////////////////////////////// + // STACK OPERATIONS + //////////////////////////////////////////////////////////////// - let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) + function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, sub(position, 1))) - if iszero(result) { - revert(0, 0) + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) } - nonce := mload(0) + mstore(sp, oldStackHead) + stackHead := mload(tempSp) + newSp := add(sp, 0x20) } - 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) + function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, position)) - if iszero(success) { - // This error should never happen - revert(0, 0) + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) } - isEVM := mload(0) + stackHead := mload(tempSp) + mstore(tempSp, oldStackHead) } - function _pushEVMFrame(_passGas, _isStatic) { - // function pushEVMFrame - // non-standard selector 0x03 - mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) - mstore(32, _passGas) + function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { + // We can not return any error here, because it would break compatibility + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) + a := oldStackHead + newSp := sub(sp, 0x20) + stackHead := mload(newSp) } - // 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 } + function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { + if iszero(lt(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } - // From precompiles/CodeOracle - function DECOMMIT_COST_PER_WORD() -> cost { cost := 4 } - function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 + mstore(sp, oldStackHead) + stackHead := item + newSp := add(sp, 0x20) + } - function _calcEVMGas(_zkevmGas) -> calczkevmGas { - calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) // TODO round up + function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { + a := oldStackHead + newSp := sub(sp, 0x20) + stackHead := mload(newSp) } - function getEVMGas() -> evmGas { - let _gas := gas() - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) + function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { + mstore(sp, oldStackHead) + stackHead := item + newSp := add(sp, 0x20) + } - switch lt(_gas, requiredGas) - case 1 { - evmGas := 0 - } - default { - evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) + function popStackCheck(sp, evmGasLeft, numInputs) { + if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { + revertWithGas(evmGasLeft) } } - 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)) + function pushStackCheck(sp, evmGasLeft, numInputs) { + if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) } - let decommitGasCost := mul(div(byteSize,32), DECOMMIT_COST_PER_WORD()) - zkevmGas := sub(zkevmGas, decommitGasCost) - if gt(zkevmGas, UINT32_MAX()) { - zkevmGas := UINT32_MAX() + } + + //////////////////////////////////////////////////////////////// + // EVM GAS MANAGER FUNCTIONALITY + //////////////////////////////////////////////////////////////// + + function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { + // function warmAccount(address account) + // non-standard selector 0x00 + // addr is packed in the same word with selector + mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) + + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32) + + if returndatasize() { + isWarm := true } } - function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft{ - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - let rtsz := returndatasize() + function isSlotWarm(key) -> isWarm { + // non-standard selector 0x01 + mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) - loadReturndataIntoActivePtr() + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) - // if (rtsz > 31) - switch gt(rtsz, 31) - case 0 { - // Unexpected return data. - _gasLeft := 0 - _eraseReturndataPointer() - } - default { - returndatacopy(0, 0, 32) - _gasLeft := mload(0) + if iszero(success) { + // This error should never happen + revert(0, 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)) } + if returndatasize() { + isWarm := true + } + } + + function warmSlot(key,currentValue) -> isWarm, originalValue { + // non-standard selector 0x02 + mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) + mstore(33,currentValue) - mstore(lastRtSzOffset, sub(rtsz, 32)) + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) - // Skip the returnData - ptrAddIntoActive(32) - } + if returndatasize() { + isWarm := true + returndatacopy(0, 0, 32) + originalValue := mload(0) + } } - function _eraseReturndataPointer() { - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + function _pushEVMFrame(_passGas, _isStatic) { + // function pushEVMFrame + // non-standard selector 0x03 + mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) + mstore(32, _passGas) - let activePtrSize := getActivePtrDataSize() - ptrShrinkIntoActive(and(activePtrSize, 0xFFFFFFFF))// uint32(activePtrSize) - mstore(lastRtSzOffset, 0) + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) } - function _saveReturndataAfterZkEVMCall() { - loadReturndataIntoActivePtr() - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + function consumeEvmFrame() -> passGas, isStatic, callerEVM { + // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) + // non-standard selector 0x04 + mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) - mstore(lastRtSzOffset, returndatasize()) - } + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) - function capGas(evmGasLeft,oldGasToPass) -> gasToPass { - let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 - gasToPass := oldGasToPass - if gt(oldGasToPass, maxGasToPass) { - gasToPass := maxGasToPass - } - } + let _returndatasize := returndatasize() + if _returndatasize { + callerEVM := true - function getMaxMemoryExpansionCost(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)) + returndatacopy(0, 0, 32) + passGas := mload(0) + + isStatic := gt(_returndatasize, 32) } } + //////////////////////////////////////////////////////////////// + // CALLS FUNCTIONALITY + //////////////////////////////////////////////////////////////// + function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize @@ -3798,13 +3612,13 @@ object "EvmEmulator" { } { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGas(evmGasLeft, gasToPass) + gasToPass := capGasForCall(evmGasLeft, gasToPass) let success, frameGasLeft := _performCall( addr, @@ -3856,13 +3670,13 @@ object "EvmEmulator" { } { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGas(evmGasLeft, gasToPass) + gasToPass := capGasForCall(evmGasLeft, gasToPass) let success, frameGasLeft := _performStaticCall( addr, @@ -3918,85 +3732,284 @@ object "EvmEmulator" { } { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } - evmGasLeft := chargeGas(evmGasLeft, gasUsed) + evmGasLeft := chargeGas(evmGasLeft, gasUsed) + + gasToPass := capGasForCall(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) + let gasUsed := sub(gasToPass, frameGasLeft) + + newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + + stackHead := success + } + + function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + switch _isEVM(addr) + case 0 { + // zkEVM native + let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) + let zkEvmGasBefore := gas() + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) + + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) // TODO check + } + } + default { + _pushEVMFrame(gasToPass, false) + success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + } + } + + function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + switch _isEVM(addr) + case 0 { + // zkEVM native + let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) + let zkEvmGasBefore := gas() + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) + + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) // TODO check + } + } + default { + _pushEVMFrame(gasToPass, true) + success := staticcall(EVM_GAS_STIPEND(), addr, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + } + } + + function _getZkEVMGasForCall(_evmGas, addr) -> zkevmGas { + // TODO CHECK COSTS CALCULATION + 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 capGasForCall(evmGasLeft,oldGasToPass) -> gasToPass { + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + gasToPass := oldGasToPass + if gt(oldGasToPass, maxGasToPass) { + gasToPass := maxGasToPass + } + } + + function getMemoryExpansionCostForCall(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)) + } + } + + // 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 _saveReturndataAfterZkEVMCall() { + loadReturndataIntoActivePtr() + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - gasToPass := capGas(evmGasLeft, gasToPass) + mstore(lastRtSzOffset, returndatasize()) + } - _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 - ) + function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft { + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + let rtsz := returndatasize() - let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - let gasUsed := sub(gasToPass, frameGasLeft) + loadReturndataIntoActivePtr() - newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + // if (rtsz > 31) + switch gt(rtsz, 31) + case 0 { + // Unexpected return data. + _gasLeft := 0 + _eraseReturndataPointer() + } + default { + returndatacopy(0, 0, 32) + _gasLeft := mload(0) - stackHead := success - } + // 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)) } - function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch _isEVM(addr) - case 0 { - // zkEVM native - let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) - let zkEvmGasBefore := gas() - success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) + mstore(lastRtSzOffset, sub(rtsz, 32)) - if gt(gasToPass, gasUsed) { - frameGasLeft := sub(gasToPass, gasUsed) // TODO check + // Skip the returnData + ptrAddIntoActive(32) } - } - default { - _pushEVMFrame(gasToPass, false) - success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - } } - function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch _isEVM(addr) - case 0 { - // zkEVM native - let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) - let zkEvmGasBefore := gas() - success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) + function _eraseReturndataPointer() { + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - if gt(gasToPass, gasUsed) { - frameGasLeft := sub(gasToPass, gasUsed) // TODO check - } - } - default { - _pushEVMFrame(gasToPass, true) - success := staticcall(EVM_GAS_STIPEND(), addr, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - } + let activePtrSize := getActivePtrDataSize() + ptrShrinkIntoActive(and(activePtrSize, 0xFFFFFFFF))// uint32(activePtrSize) + mstore(lastRtSzOffset, 0) } - 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 - } - } - } - } + //////////////////////////////////////////////////////////////// + // CREATE FUNCTIONALITY + //////////////////////////////////////////////////////////////// function _fetchConstructorReturnGas() -> gasLeft { mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) @@ -4014,7 +4027,7 @@ object "EvmEmulator" { function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { _eraseReturndataPointer() - let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) + let gasForTheCall := capGasForCall(evmGasLeftOld,INF_PASS_GAS()) if lt(selfbalance(),value) { revertWithGas(evmGasLeftOld) @@ -4084,75 +4097,6 @@ object "EvmEmulator" { 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, oldStackHead) -> evmGasLeft, sp, stackHead { - evmGasLeft := chargeGas(evmGas, 100) - - let addr, dest, offset, len - popStackCheck(oldSp, evmGasLeft, 4) - addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - // 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, oldStackHead) -> evmGasLeft, sp, stackHead { evmGasLeft := chargeGas(evmGas, 32000) @@ -4234,6 +4178,78 @@ object "EvmEmulator" { result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt, stackHead) } + //////////////////////////////////////////////////////////////// + // EXTCODECOPY FUNCTIONALITY + //////////////////////////////////////////////////////////////// + + 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, oldStackHead) -> evmGasLeft, sp, stackHead { + evmGasLeft := chargeGas(evmGas, 100) + + let addr, dest, offset, len + popStackCheck(oldSp, evmGasLeft, 4) + addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + + // 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 $llvm_NoInline_llvm$_simulate( isCallerEVM, @@ -5655,16 +5671,22 @@ object "EvmEmulator" { offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset,size, evmGasLeft) + checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) - evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) - + 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) - revert(offset,size) + if eq(isCallerEVM, 1) { + offset := sub(offset, 32) + size := add(size, 32) + + // include gas + mstore(offset, evmGasLeft) + } + + revert(offset, size) } case 0xFE { // OP_INVALID evmGasLeft := 0 @@ -6028,7 +6050,7 @@ object "EvmEmulator" { let evmGasLeft, isStatic, isCallerEVM := consumeEvmFrame() if iszero(isCallerEVM) { - evmGasLeft := getEVMGas() + evmGasLeft := getEvmGasFromContext() isStatic := getIsStaticFromCallFlags() } diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index ffbb04cae..b9ed6d2b3 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -79,7 +79,7 @@ object "EvmEmulator" { getConstructorBytecode() if iszero(isCallerEVM) { - evmGasLeft := getEVMGas() + evmGasLeft := getEvmGasFromContext() } let offset, len, gasToReturn := simulate(isCallerEVM, evmGasLeft, false) @@ -124,7 +124,7 @@ object "EvmEmulator" { let evmGasLeft, isStatic, isCallerEVM := consumeEvmFrame() if iszero(isCallerEVM) { - evmGasLeft := getEVMGas() + evmGasLeft := getEvmGasFromContext() isStatic := getIsStaticFromCallFlags() } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 3dfbcd3a8..62bd36e1d 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -1,3 +1,7 @@ +//////////////////////////////////////////////////////////////// +// CONSTANTS +//////////////////////////////////////////////////////////////// + function ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008002 } @@ -18,12 +22,8 @@ function EVM_GAS_MANAGER_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008013 } -function DEBUG_SLOT_OFFSET() -> offset { - offset := mul(32, 32) // TODO cleanup -} - function LAST_RETURNDATA_SIZE_OFFSET() -> offset { - offset := add(DEBUG_SLOT_OFFSET(), mul(5, 32)) + offset := mul(32, 32) } function STACK_OFFSET() -> offset { @@ -34,10 +34,6 @@ 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 } @@ -62,94 +58,75 @@ function MAX_UINT() -> max_uint { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } -function $llvm_NoInline_llvm$_revert() { - revert(0, 0) +function INF_PASS_GAS() -> inf { + inf := 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) -} +// 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 } -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)) -} +// From precompiles/CodeOracle +function DECOMMIT_COST_PER_WORD() -> cost { cost := 4 } -function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { - evmGasLeft := chargeGas(evmGas, 3) - let tempSp := sub(sp, mul(0x20, sub(position, 1))) +function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } +//////////////////////////////////////////////////////////////// +// GENERAL FUNCTIONS +//////////////////////////////////////////////////////////////// - mstore(sp, oldStackHead) - stackHead := mload(tempSp) - newSp := add(sp, 0x20) +function $llvm_NoInline_llvm$_revert() { + revert(0, 0) } -function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { - evmGasLeft := chargeGas(evmGas, 3) - let tempSp := sub(sp, mul(0x20, position)) - - if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := mload(tempSp) - mstore(tempSp, oldStackHead) +function revertWithGas(evmGasLeft) { + mstore(0, evmGasLeft) + revert(0, 32) } -function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { - // We can not return any error here, because it would break compatibility - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) +function chargeGas(prevGas, toCharge) -> gasRemaining { + if lt(prevGas, toCharge) { + revertWithGas(0) } - a := oldStackHead - newSp := sub(sp, 0x20) - stackHead := mload(newSp) + gasRemaining := sub(prevGas, toCharge) } -function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { - if iszero(lt(sp, BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) +function checkMemOverflowByOffset(offset, evmGasLeft) { + if gt(offset, MAX_POSSIBLE_MEM()) { + mstore(0, evmGasLeft) + revert(0, 32) } - - mstore(sp, oldStackHead) - stackHead := item - newSp := add(sp, 0x20) } -function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { - a := oldStackHead - newSp := sub(sp, 0x20) - stackHead := mload(newSp) +function checkMemOverflow(location, evmGasLeft) { + if gt(location, MAX_MEMORY_FRAME()) { + mstore(0, evmGasLeft) + revert(0, 32) + } } -function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { - mstore(sp, oldStackHead) - stackHead := item - newSp := add(sp, 0x20) +function checkOverflow(data1, data2, evmGasLeft) { + if lt(add(data1, data2), data2) { + revertWithGas(evmGasLeft) + } } -function popStackCheck(sp, evmGasLeft, numInputs) { - if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { - revertWithGas(evmGasLeft) +// 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 pushStackCheck(sp, evmGasLeft, numInputs) { - if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) +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 getCodeAddress() -> addr { @@ -180,6 +157,35 @@ function ptrShrinkIntoActive(_dest) { verbatim_1i_0o("active_ptr_shrink_assign", _dest) } +function getIsStaticFromCallFlags() -> isStatic { + isStatic := verbatim_0i_1o("get_global::call_flags") + isStatic := iszero(iszero(and(isStatic, 0x04))) +} + +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 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 _getRawCodeHash(account) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) @@ -194,11 +200,6 @@ function _getRawCodeHash(account) -> hash { 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) @@ -261,32 +262,6 @@ function getDeployedBytecode() { mstore(BYTECODE_OFFSET(), codeLen) } -function consumeEvmFrame() -> passGas, isStatic, callerEVM { - // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) - // non-standard selector 0x04 - mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) - - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) - - let _returndatasize := returndatasize() - if _returndatasize { - callerEVM := true - - returndatacopy(0, 0, 32) - passGas := mload(0) - - isStatic := gt(_returndatasize, 32) - } -} - -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) { @@ -308,162 +283,11 @@ function bitLength(n) -> bitLen { 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 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()) +// 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 @@ -480,38 +304,6 @@ function expandMemory(newSize) -> gasCost { } } -function isSlotWarm(key) -> isWarm { - // non-standard selector 0x01 - mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) - mstore(1, key) - - let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - if returndatasize() { - isWarm := true - } -} - -function warmSlot(key,currentValue) -> isWarm, originalValue { - // non-standard selector 0x02 - mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) - mstore(1, key) - mstore(33,currentValue) - - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) - - if returndatasize() { - isWarm := true - returndatacopy(0, 0, 32) - originalValue := mload(0) - } -} - function performSystemCall( to, dataLength, @@ -533,181 +325,192 @@ function performSystemCall( } } +function _isEVM(_addr) -> isEVM { + // function isAccountEVM(address _addr) external view returns (bool); + mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) + mstore(4, _addr) -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 + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) - newOffset := sub(offset, 32) - newSize := add(size, 32) + if iszero(success) { + // This error should never happen + revert(0, 0) } + + isEVM := mload(0) } -function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { - // function warmAccount(address account) - // non-standard selector 0x00 - // addr is packed in the same word with selector - mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) +function zkVmGasToEvmGas(_zkevmGas) -> calczkevmGas { + calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) // TODO round up +} - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32) +function getEvmGasFromContext() -> evmGas { + let _gas := gas() + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) // TODO CHECK GAS MECHANICS - if returndatasize() { - isWarm := true + switch lt(_gas, requiredGas) + case 1 { + evmGas := 0 + } + default { + evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) } } -function getRawNonce(addr) -> nonce { - mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) - mstore(4, addr) +//////////////////////////////////////////////////////////////// +// STACK OPERATIONS +//////////////////////////////////////////////////////////////// - let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) +function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, sub(position, 1))) - if iszero(result) { - revert(0, 0) + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) } - nonce := mload(0) + mstore(sp, oldStackHead) + stackHead := mload(tempSp) + newSp := add(sp, 0x20) } -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) +function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stackHead { + evmGasLeft := chargeGas(evmGas, 3) + let tempSp := sub(sp, mul(0x20, position)) - if iszero(success) { - // This error should never happen - revert(0, 0) + if lt(tempSp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) } - isEVM := mload(0) + stackHead := mload(tempSp) + mstore(tempSp, oldStackHead) } -function _pushEVMFrame(_passGas, _isStatic) { - // function pushEVMFrame - // non-standard selector 0x03 - mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) - mstore(32, _passGas) +function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { + // We can not return any error here, because it would break compatibility + if lt(sp, STACK_OFFSET()) { + revertWithGas(evmGasLeft) + } - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) + a := oldStackHead + newSp := sub(sp, 0x20) + stackHead := mload(newSp) } -// 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 } +function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { + if iszero(lt(sp, BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) + } -// From precompiles/CodeOracle -function DECOMMIT_COST_PER_WORD() -> cost { cost := 4 } -function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 + mstore(sp, oldStackHead) + stackHead := item + newSp := add(sp, 0x20) +} -function _calcEVMGas(_zkevmGas) -> calczkevmGas { - calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) // TODO round up +function popStackItemWithoutCheck(sp, oldStackHead) -> a, newSp, stackHead { + a := oldStackHead + newSp := sub(sp, 0x20) + stackHead := mload(newSp) } -function getEVMGas() -> evmGas { - let _gas := gas() - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) +function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { + mstore(sp, oldStackHead) + stackHead := item + newSp := add(sp, 0x20) +} - switch lt(_gas, requiredGas) - case 1 { - evmGas := 0 - } - default { - evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) +function popStackCheck(sp, evmGasLeft, numInputs) { + if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { + revertWithGas(evmGasLeft) } } -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 pushStackCheck(sp, evmGasLeft, numInputs) { + if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { + revertWithGas(evmGasLeft) } } -function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft{ - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - let rtsz := returndatasize() +//////////////////////////////////////////////////////////////// +// EVM GAS MANAGER FUNCTIONALITY +//////////////////////////////////////////////////////////////// - loadReturndataIntoActivePtr() +function $llvm_AlwaysInline_llvm$_warmAddress(addr) -> isWarm { + // function warmAccount(address account) + // non-standard selector 0x00 + // addr is packed in the same word with selector + mstore(0, and(addr, 0xffffffffffffffffffffffffffffffffffffffff)) - // if (rtsz > 31) - switch gt(rtsz, 31) - case 0 { - // Unexpected return data. - _gasLeft := 0 - _eraseReturndataPointer() - } - default { - returndatacopy(0, 0, 32) - _gasLeft := mload(0) + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 32) - // 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)) } + if returndatasize() { + isWarm := true + } +} + +function isSlotWarm(key) -> isWarm { + // non-standard selector 0x01 + mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) - mstore(lastRtSzOffset, sub(rtsz, 32)) + let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) - // Skip the returnData - ptrAddIntoActive(32) - } + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + if returndatasize() { + isWarm := true + } } -function _eraseReturndataPointer() { - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() +function warmSlot(key,currentValue) -> isWarm, originalValue { + // non-standard selector 0x02 + mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) + mstore(1, key) + mstore(33,currentValue) - let activePtrSize := getActivePtrDataSize() - ptrShrinkIntoActive(and(activePtrSize, 0xFFFFFFFF))// uint32(activePtrSize) - mstore(lastRtSzOffset, 0) + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) + + if returndatasize() { + isWarm := true + returndatacopy(0, 0, 32) + originalValue := mload(0) + } } -function _saveReturndataAfterZkEVMCall() { - loadReturndataIntoActivePtr() - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() +function _pushEVMFrame(_passGas, _isStatic) { + // function pushEVMFrame + // non-standard selector 0x03 + mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) + mstore(32, _passGas) - mstore(lastRtSzOffset, returndatasize()) + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) } -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 consumeEvmFrame() -> passGas, isStatic, callerEVM { + // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) + // non-standard selector 0x04 + mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) -function getMaxMemoryExpansionCost(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)) + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) + + let _returndatasize := returndatasize() + if _returndatasize { + callerEVM := true + + returndatacopy(0, 0, 32) + passGas := mload(0) + + isStatic := gt(_returndatasize, 32) } } +//////////////////////////////////////////////////////////////// +// CALLS FUNCTIONALITY +//////////////////////////////////////////////////////////////// + function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize @@ -750,13 +553,13 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe } { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGas(evmGasLeft, gasToPass) + gasToPass := capGasForCall(evmGasLeft, gasToPass) let success, frameGasLeft := _performCall( addr, @@ -808,13 +611,13 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s } { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGas(evmGasLeft, gasToPass) + gasToPass := capGasForCall(evmGasLeft, gasToPass) let success, frameGasLeft := _performStaticCall( addr, @@ -870,85 +673,284 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEv } { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } - evmGasLeft := chargeGas(evmGasLeft, gasUsed) + evmGasLeft := chargeGas(evmGasLeft, gasUsed) + + gasToPass := capGasForCall(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) + let gasUsed := sub(gasToPass, frameGasLeft) + + newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + + stackHead := success +} + +function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + switch _isEVM(addr) + case 0 { + // zkEVM native + let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) + let zkEvmGasBefore := gas() + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) + + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) // TODO check + } + } + default { + _pushEVMFrame(gasToPass, false) + success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + } +} + +function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + switch _isEVM(addr) + case 0 { + // zkEVM native + let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) + let zkEvmGasBefore := gas() + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) + + if gt(gasToPass, gasUsed) { + frameGasLeft := sub(gasToPass, gasUsed) // TODO check + } + } + default { + _pushEVMFrame(gasToPass, true) + success := staticcall(EVM_GAS_STIPEND(), addr, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + } +} + +function _getZkEVMGasForCall(_evmGas, addr) -> zkevmGas { + // TODO CHECK COSTS CALCULATION + 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 capGasForCall(evmGasLeft,oldGasToPass) -> gasToPass { + let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 + gasToPass := oldGasToPass + if gt(oldGasToPass, maxGasToPass) { + gasToPass := maxGasToPass + } +} + +function getMemoryExpansionCostForCall(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)) + } +} + +// 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 + } +} - gasToPass := capGas(evmGasLeft, gasToPass) +function _saveReturndataAfterZkEVMCall() { + loadReturndataIntoActivePtr() + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - _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 - ) + mstore(lastRtSzOffset, returndatasize()) +} - let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - let gasUsed := sub(gasToPass, frameGasLeft) +function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft { + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() + let rtsz := returndatasize() - newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + loadReturndataIntoActivePtr() - stackHead := success -} + // if (rtsz > 31) + switch gt(rtsz, 31) + case 0 { + // Unexpected return data. + _gasLeft := 0 + _eraseReturndataPointer() + } + default { + returndatacopy(0, 0, 32) + _gasLeft := mload(0) -function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch _isEVM(addr) - case 0 { - // zkEVM native - let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) - let zkEvmGasBefore := gas() - success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) + // 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)) } - if gt(gasToPass, gasUsed) { - frameGasLeft := sub(gasToPass, gasUsed) // TODO check + mstore(lastRtSzOffset, sub(rtsz, 32)) + + // Skip the returnData + ptrAddIntoActive(32) } - } - default { - _pushEVMFrame(gasToPass, false) - success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - } } -function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch _isEVM(addr) - case 0 { - // zkEVM native - let zkEvmGasToPass := _getZkEVMGas(gasToPass, addr) - let zkEvmGasBefore := gas() - success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := _calcEVMGas(sub(zkEvmGasBefore, gas())) +function _eraseReturndataPointer() { + let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - if gt(gasToPass, gasUsed) { - frameGasLeft := sub(gasToPass, gasUsed) // TODO check - } - } - default { - _pushEVMFrame(gasToPass, true) - success := staticcall(EVM_GAS_STIPEND(), addr, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - } + let activePtrSize := getActivePtrDataSize() + ptrShrinkIntoActive(and(activePtrSize, 0xFFFFFFFF))// uint32(activePtrSize) + mstore(lastRtSzOffset, 0) } -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 - } - } - } -} +//////////////////////////////////////////////////////////////// +// CREATE FUNCTIONALITY +//////////////////////////////////////////////////////////////// function _fetchConstructorReturnGas() -> gasLeft { mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) @@ -966,7 +968,7 @@ function _fetchConstructorReturnGas() -> gasLeft { function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { _eraseReturndataPointer() - let gasForTheCall := capGas(evmGasLeftOld,INF_PASS_GAS()) + let gasForTheCall := capGasForCall(evmGasLeftOld,INF_PASS_GAS()) if lt(selfbalance(),value) { revertWithGas(evmGasLeftOld) @@ -1036,75 +1038,6 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO 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, oldStackHead) -> evmGasLeft, sp, stackHead { - evmGasLeft := chargeGas(evmGas, 100) - - let addr, dest, offset, len - popStackCheck(oldSp, evmGasLeft, 4) - addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - // 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, oldStackHead) -> evmGasLeft, sp, stackHead { evmGasLeft := chargeGas(evmGas, 32000) @@ -1185,3 +1118,76 @@ function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt, stackHead) } + +//////////////////////////////////////////////////////////////// +// EXTCODECOPY FUNCTIONALITY +//////////////////////////////////////////////////////////////// + +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, oldStackHead) -> evmGasLeft, sp, stackHead { + evmGasLeft := chargeGas(evmGas, 100) + + let addr, dest, offset, len + popStackCheck(oldSp, evmGasLeft, 4) + addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + + // 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()))) + } +} \ No newline at end of file diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 36bf5f53d..f1531a82d 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -1409,16 +1409,22 @@ for { } true { } { offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset,size, evmGasLeft) + checkOverflow(offset, size, evmGasLeft) checkMemOverflowByOffset(add(offset, size), evmGasLeft) - evmGasLeft := chargeGas(evmGasLeft,expandMemory(add(offset,size))) - + 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) - revert(offset,size) + if eq(isCallerEVM, 1) { + offset := sub(offset, 32) + size := add(size, 32) + + // include gas + mstore(offset, evmGasLeft) + } + + revert(offset, size) } case 0xFE { // OP_INVALID evmGasLeft := 0 From ee5ad27527272cf4cae70a2776f19c224f968c74 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 24 Oct 2024 16:24:08 +0200 Subject: [PATCH 091/183] chore(EVM): Use returndatacopy in emulator internal static calls (#973) --- system-contracts/SystemContractsHashes.json | 4 +-- system-contracts/contracts/EvmEmulator.yul | 36 ++++++++++++------- .../EvmEmulatorFunctions.template.yul | 14 +++++--- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index f91e2152a..47dd50e52 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000d553d34b21e5609df63cce2b19a00a700d51acd7398d144b9a83d5ab163", - "sourceCodeHash": "0x59010ac2de66c76109c3d150439d09afae1f70a55a39ff2d14f5ac3b13e6ed10" + "bytecodeHash": "0x01000cb73b38a6656c56e24989ef1556ce7d2b7111a7072b1b98c635a9eaca08", + "sourceCodeHash": "0x7acbc848ada6fbd9be8ba40d601c5b8df8ee38f75facc1ee6fb0862495c6e0e3" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 266c1150f..b0e8a45a4 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -227,12 +227,13 @@ object "EvmEmulator" { mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) mstore(4, addr) - let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) + let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 0) if iszero(result) { revert(0, 0) } + returndatacopy(0, 0, 32) nonce := mload(0) } @@ -240,13 +241,14 @@ object "EvmEmulator" { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + returndatacopy(0, 0, 32) hash := mload(0) } @@ -380,13 +382,14 @@ object "EvmEmulator" { mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) mstore(4, _addr) - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + returndatacopy(0, 0, 32) isEVM := mload(0) } @@ -756,7 +759,8 @@ object "EvmEmulator" { // zkEVM native let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() - success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, 0, 0) + returndatacopy(0, retOffset, retSize) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) @@ -777,7 +781,8 @@ object "EvmEmulator" { // zkEVM native let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() - success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, 0, 0) + returndatacopy(0, retOffset, retSize) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) @@ -1005,13 +1010,14 @@ object "EvmEmulator" { function _fetchConstructorReturnGas() -> gasLeft { mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 32) + let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + returndatacopy(0, 0, 32) gasLeft := mload(0) } @@ -3236,12 +3242,13 @@ object "EvmEmulator" { mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) mstore(4, addr) - let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) + let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 0) if iszero(result) { revert(0, 0) } + returndatacopy(0, 0, 32) nonce := mload(0) } @@ -3249,13 +3256,14 @@ object "EvmEmulator" { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + returndatacopy(0, 0, 32) hash := mload(0) } @@ -3389,13 +3397,14 @@ object "EvmEmulator" { mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) mstore(4, _addr) - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + returndatacopy(0, 0, 32) isEVM := mload(0) } @@ -3765,7 +3774,8 @@ object "EvmEmulator" { // zkEVM native let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() - success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, 0, 0) + returndatacopy(0, retOffset, retSize) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) @@ -3786,7 +3796,8 @@ object "EvmEmulator" { // zkEVM native let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() - success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, 0, 0) + returndatacopy(0, retOffset, retSize) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) @@ -4014,13 +4025,14 @@ object "EvmEmulator" { function _fetchConstructorReturnGas() -> gasLeft { mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 32) + let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + returndatacopy(0, 0, 32) gasLeft := mload(0) } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 62bd36e1d..cc011da2f 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -177,12 +177,13 @@ function getRawNonce(addr) -> nonce { mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) mstore(4, addr) - let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 32) + let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 0) if iszero(result) { revert(0, 0) } + returndatacopy(0, 0, 32) nonce := mload(0) } @@ -190,13 +191,14 @@ function _getRawCodeHash(account) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + returndatacopy(0, 0, 32) hash := mload(0) } @@ -330,13 +332,14 @@ function _isEVM(_addr) -> isEVM { mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) mstore(4, _addr) - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 32) + let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + returndatacopy(0, 0, 32) isEVM := mload(0) } @@ -727,7 +730,7 @@ function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, re // zkEVM native let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() - success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, 0, 0) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) @@ -955,13 +958,14 @@ function _eraseReturndataPointer() { function _fetchConstructorReturnGas() -> gasLeft { mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 32) + let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) if iszero(success) { // This error should never happen revert(0, 0) } + returndatacopy(0, 0, 32) gasLeft := mload(0) } From e24cd0952e6d7ad8316a3c00014e2fc73bb6de1f Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 24 Oct 2024 16:27:51 +0200 Subject: [PATCH 092/183] Preprocess emulator --- system-contracts/SystemContractsHashes.json | 4 ++-- system-contracts/contracts/EvmEmulator.yul | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 47dd50e52..ac15af296 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cb73b38a6656c56e24989ef1556ce7d2b7111a7072b1b98c635a9eaca08", - "sourceCodeHash": "0x7acbc848ada6fbd9be8ba40d601c5b8df8ee38f75facc1ee6fb0862495c6e0e3" + "bytecodeHash": "0x01000cc9cf80d427d7a3404417eecde37dc4d0cc6aad93579e70533f2ab735d9", + "sourceCodeHash": "0xa93f827537dbf02fd886a7cb61cb185c18706bf7414603a0d728da5e3513cac3" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index b0e8a45a4..ae34f6d3f 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -759,8 +759,7 @@ object "EvmEmulator" { // zkEVM native let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() - success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, 0, 0) - returndatacopy(0, retOffset, retSize) + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) @@ -782,7 +781,6 @@ object "EvmEmulator" { let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, 0, 0) - returndatacopy(0, retOffset, retSize) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) @@ -3774,8 +3772,7 @@ object "EvmEmulator" { // zkEVM native let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() - success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, 0, 0) - returndatacopy(0, retOffset, retSize) + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) @@ -3797,7 +3794,6 @@ object "EvmEmulator" { let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, 0, 0) - returndatacopy(0, retOffset, retSize) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) From 8b136ae37a0a095dd2f132f3b8013c140ada4511 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 24 Oct 2024 19:54:32 +0200 Subject: [PATCH 093/183] fix(EVM): Panic instead of reverts in case of critical errors (#974) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 1260 ++++++++--------- .../evm-emulator/EvmEmulator.template.yul | 2 +- .../EvmEmulatorFunctions.template.yul | 150 +- .../evm-emulator/EvmEmulatorLoop.template.yul | 479 +++---- 5 files changed, 877 insertions(+), 1018 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index ac15af296..057e59112 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cc9cf80d427d7a3404417eecde37dc4d0cc6aad93579e70533f2ab735d9", - "sourceCodeHash": "0xa93f827537dbf02fd886a7cb61cb185c18706bf7414603a0d728da5e3513cac3" + "bytecodeHash": "0x01000cc15cda7e95291300368963dc790e59bea406b834bc2fe487c8ff05c31b", + "sourceCodeHash": "0x7efddc39cf95e293f4e08683cda2726cc6541de60f517f0150c894bef0336342" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index ae34f6d3f..96d3ffb7a 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -135,31 +135,35 @@ object "EvmEmulator" { revert(0, 32) } + function panic() { + revert(0, 0) + } + function chargeGas(prevGas, toCharge) -> gasRemaining { if lt(prevGas, toCharge) { - revertWithGas(0) + panic() } gasRemaining := sub(prevGas, toCharge) } - function checkMemOverflowByOffset(offset, evmGasLeft) { - if gt(offset, MAX_POSSIBLE_MEM()) { - mstore(0, evmGasLeft) - revert(0, 32) + function checkMemIsAccessible(index, offset) { + checkOverflow(index, offset) + + if gt(add(index, offset), MAX_MEMORY_FRAME()) { + panic() } } - function checkMemOverflow(location, evmGasLeft) { + function checkMemOverflow(location) { if gt(location, MAX_MEMORY_FRAME()) { - mstore(0, evmGasLeft) - revert(0, 32) + panic() } } - function checkOverflow(data1, data2, evmGasLeft) { + function checkOverflow(data1, data2) { if lt(add(data1, data2), data2) { - revertWithGas(evmGasLeft) + panic() } } @@ -419,7 +423,7 @@ object "EvmEmulator" { let tempSp := sub(sp, mul(0x20, sub(position, 1))) if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } mstore(sp, oldStackHead) @@ -432,17 +436,17 @@ object "EvmEmulator" { let tempSp := sub(sp, mul(0x20, position)) if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } stackHead := mload(tempSp) mstore(tempSp, oldStackHead) } - function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { + function popStackItem(sp, oldStackHead) -> a, newSp, stackHead { // We can not return any error here, because it would break compatibility if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } a := oldStackHead @@ -450,9 +454,9 @@ object "EvmEmulator" { stackHead := mload(newSp) } - function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { + function pushStackItem(sp, item, oldStackHead) -> newSp, stackHead { if iszero(lt(sp, BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) + panic() } mstore(sp, oldStackHead) @@ -472,18 +476,26 @@ object "EvmEmulator" { newSp := add(sp, 0x20) } - function popStackCheck(sp, evmGasLeft, numInputs) { + function popStackCheck(sp, numInputs) { if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } } - function pushStackCheck(sp, evmGasLeft, numInputs) { + function pushStackCheck(sp, numInputs) { if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) + panic() } } + function accessStackHead(sp, stackHead) -> value { + if lt(sp, STACK_OFFSET()) { + panic() + } + + value := stackHead + } + //////////////////////////////////////////////////////////////// // EVM GAS MANAGER FUNCTIONALITY //////////////////////////////////////////////////////////////// @@ -567,7 +579,7 @@ object "EvmEmulator" { function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 7) + popStackCheck(oldSp, 7) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -577,12 +589,8 @@ object "EvmEmulator" { addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - - checkOverflow(argsOffset,argsSize, evmGasLeft) - checkOverflow(retOffset, retSize, evmGasLeft) - - checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) - checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) // static_gas = 0 // dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + positive_value_cost + value_to_empty_account_cost @@ -606,7 +614,7 @@ object "EvmEmulator" { } { - let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } @@ -643,7 +651,7 @@ object "EvmEmulator" { function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { let gasToPass,addr, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 6) + popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -652,11 +660,8 @@ object "EvmEmulator" { addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - checkOverflow(argsOffset,argsSize, evmGasLeft) - checkOverflow(retOffset, retSize, evmGasLeft) - - checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) - checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) let gasUsed := 100 if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -664,7 +669,7 @@ object "EvmEmulator" { } { - let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } @@ -701,7 +706,7 @@ object "EvmEmulator" { function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEvmGasLeft, sp, stackHead { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 6) + popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -710,15 +715,8 @@ object "EvmEmulator" { 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) - } + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) let gasUsed := 100 if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -726,12 +724,16 @@ object "EvmEmulator" { } { - let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } evmGasLeft := chargeGas(evmGasLeft, gasUsed) + if iszero(_isEVM(addr)) { + revertWithGas(evmGasLeft) + } + gasToPass := capGasForCall(evmGasLeft, gasToPass) _pushEVMFrame(gasToPass, isStatic) @@ -818,7 +820,7 @@ object "EvmEmulator" { } } - function getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) -> maxExpand { + function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> maxExpand { maxExpand := add(retOffset, retSize) switch lt(maxExpand, add(argsOffset, argsSize)) case 0 { @@ -1022,15 +1024,15 @@ object "EvmEmulator" { function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { _eraseReturndataPointer() - let gasForTheCall := capGasForCall(evmGasLeftOld,INF_PASS_GAS()) + let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) - if lt(selfbalance(),value) { + if lt(selfbalance(), value) { // TODO optimize revertWithGas(evmGasLeftOld) } - offset := add(MEM_OFFSET_INNER(), offset) + offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check - pushStackCheck(sp, evmGasLeftOld, 4) + pushStackCheck(sp, 4) sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) @@ -1096,20 +1098,19 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { - revertWithGas(evmGasLeft) // TODO review + panic() } let value, offset, size - popStackCheck(oldSp, evmGasLeft, 3) + popStackCheck(oldSp, 3) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { - revertWithGas(evmGasLeft) + revertWithGas(evmGasLeft) // TODO check } if gt(value, balance(address())) { @@ -1138,19 +1139,18 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { - revertWithGas(evmGasLeft) + panic() } let value, offset, size, salt - popStackCheck(oldSp, evmGasLeft, 4) + popStackCheck(oldSp, 4) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { revertWithGas(evmGasLeft) @@ -1215,36 +1215,6 @@ object "EvmEmulator" { $llvm_AlwaysInline_llvm$_copyRest(dest_end, 0, rest_len) } } - - function performExtCodeCopy(evmGas,oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { - evmGasLeft := chargeGas(evmGas, 100) - - let addr, dest, offset, len - popStackCheck(oldSp, evmGasLeft, 4) - addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - // 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 simulate( isCallerEVM, @@ -1275,7 +1245,7 @@ object "EvmEmulator" { case 0x01 { // OP_ADD evmGasLeft := chargeGas(evmGasLeft, 3) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := add(a, stackHead) @@ -1285,7 +1255,7 @@ object "EvmEmulator" { case 0x02 { // OP_MUL evmGasLeft := chargeGas(evmGasLeft, 5) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := mul(a, stackHead) @@ -1294,7 +1264,7 @@ object "EvmEmulator" { case 0x03 { // OP_SUB evmGasLeft := chargeGas(evmGasLeft, 3) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := sub(a, stackHead) @@ -1304,7 +1274,7 @@ object "EvmEmulator" { case 0x04 { // OP_DIV evmGasLeft := chargeGas(evmGasLeft, 5) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := div(a, stackHead) @@ -1314,7 +1284,7 @@ object "EvmEmulator" { case 0x05 { // OP_SDIV evmGasLeft := chargeGas(evmGasLeft, 5) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := sdiv(a, stackHead) @@ -1325,7 +1295,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 5) let a - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := mod(a, stackHead) @@ -1335,7 +1305,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 5) let a - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := smod(a, stackHead) @@ -1346,7 +1316,7 @@ object "EvmEmulator" { let a, b, N - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) b, sp, N := popStackItemWithoutCheck(sp, stackHead) stackHead := addmod(a, b, N) @@ -1358,7 +1328,7 @@ object "EvmEmulator" { let a, b, N - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) b, sp, N := popStackItemWithoutCheck(sp, stackHead) @@ -1370,7 +1340,7 @@ object "EvmEmulator" { let a, exponent - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) stackHead := exp(a, exponent) @@ -1388,7 +1358,7 @@ object "EvmEmulator" { let b, x - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) b, sp, x := popStackItemWithoutCheck(sp, stackHead) stackHead := signextend(b, x) @@ -1399,7 +1369,7 @@ object "EvmEmulator" { let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := lt(a, b) @@ -1410,7 +1380,7 @@ object "EvmEmulator" { let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead:= gt(a, b) @@ -1421,7 +1391,7 @@ object "EvmEmulator" { let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := slt(a, b) @@ -1431,7 +1401,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := sgt(a, b) @@ -1441,7 +1411,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := eq(a, b) @@ -1450,10 +1420,7 @@ object "EvmEmulator" { case 0x15 { // OP_ISZERO evmGasLeft := chargeGas(evmGasLeft, 3) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - stackHead := iszero(stackHead) + stackHead := iszero(accessStackHead(sp, stackHead)) ip := add(ip, 1) } @@ -1461,7 +1428,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := and(a,b) @@ -1471,7 +1438,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := or(a,b) @@ -1481,7 +1448,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := xor(a, b) @@ -1490,11 +1457,7 @@ object "EvmEmulator" { case 0x19 { // OP_NOT evmGasLeft := chargeGas(evmGasLeft, 3) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := not(stackHead) + stackHead := not(accessStackHead(sp, stackHead)) ip := add(ip, 1) } @@ -1502,7 +1465,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let i, x - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) i, sp, x := popStackItemWithoutCheck(sp, stackHead) stackHead := byte(i, x) @@ -1512,7 +1475,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let shift, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) shift, sp, value := popStackItemWithoutCheck(sp, stackHead) stackHead := shl(shift, value) @@ -1522,7 +1485,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let shift, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) shift, sp, value := popStackItemWithoutCheck(sp, stackHead) stackHead := shr(shift, value) @@ -1532,7 +1495,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let shift, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) shift, sp, value := popStackItemWithoutCheck(sp, stackHead) stackHead := sar(shift, value) @@ -1543,11 +1506,11 @@ object "EvmEmulator" { let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) + let keccak := keccak256(add(MEM_OFFSET_INNER(), offset), size) // When an offset is first accessed (either read or write), memory may trigger @@ -1563,17 +1526,13 @@ object "EvmEmulator" { case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, address(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, address(), stackHead) ip := add(ip, 1) } case 0x31 { // OP_BALANCE evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let addr := stackHead + let addr := accessStackHead(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -1587,36 +1546,32 @@ object "EvmEmulator" { case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, origin(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, origin(), stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, caller(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, caller(), stackHead) ip := add(ip, 1) } case 0x34 { // OP_CALLVALUE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, callvalue(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, callvalue(), stackHead) ip := add(ip, 1) } case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) - - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - stackHead := calldataload(stackHead) + stackHead := calldataload(accessStackHead(sp, stackHead)) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, calldatasize(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, calldatasize(), stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -1624,13 +1579,12 @@ object "EvmEmulator" { let destOffset, offset, size - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(destOffset, size, evmGasLeft) - checkMemOverflowByOffset(add(destOffset,size), evmGasLeft) + checkMemIsAccessible(destOffset, size) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -1645,52 +1599,49 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 2) let bytecodeLen := mload(BYTECODE_OFFSET()) - sp, stackHead := pushStackItem(sp, bytecodeLen, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, bytecodeLen, stackHead) ip := add(ip, 1) } case 0x39 { // OP_CODECOPY evmGasLeft := chargeGas(evmGasLeft, 3) - let dst, offset, len + let dstOffset, sourceOffset, len - popStackCheck(sp, evmGasLeft, 3) - dst, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + popStackCheck(sp, 3) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + sourceOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + checkMemIsAccessible(dstOffset, len) + // 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))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dstOffset, len))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - dst := add(dst, MEM_OFFSET_INNER()) - offset := add(add(offset, BYTECODE_OFFSET()), 32) + dstOffset := add(dstOffset, MEM_OFFSET_INNER()) + sourceOffset := add(add(sourceOffset, BYTECODE_OFFSET()), 32) - checkOverflow(dst,len, evmGasLeft) - checkOverflow(offset,len, evmGasLeft) - checkMemOverflow(add(dst, len), evmGasLeft) + checkOverflow(sourceOffset, len) // Check bytecode overflow - if gt(add(offset, len), sub(MEM_OFFSET(), 1)) { - revertWithGas(evmGasLeft) + if gt(add(sourceOffset, len), sub(MEM_OFFSET(), 1)) { + panic() } - $llvm_AlwaysInline_llvm$_memcpy(dst, offset, len) + $llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, len) ip := add(ip, 1) } case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, gasprice(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, gasprice(), stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - let addr := stackHead + let addr := accessStackHead(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -1704,47 +1655,76 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY - evmGasLeft, sp, stackHead := performExtCodeCopy(evmGasLeft, sp, stackHead) + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr, dest, offset, len + popStackCheck(sp, 4) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + + checkMemIsAccessible(dest, len) + + // 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()))) + } + ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) - sp, stackHead := pushStackItem(sp, rdz, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, rdz, stackHead) ip := add(ip, 1) } case 0x3E { // OP_RETURNDATACOPY evmGasLeft := chargeGas(evmGasLeft, 3) - let dest, offset, len - popStackCheck(sp, evmGasLeft, 3) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + let dstOffset, sourceOffset, len + popStackCheck(sp, 3) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + sourceOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset,len, evmGasLeft) - if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { - revertWithGas(evmGasLeft) - } + checkMemIsAccessible(dstOffset, len) // 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))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dstOffset, len))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - copyActivePtrData(add(MEM_OFFSET_INNER(), dest), offset, len) + checkOverflow(sourceOffset, len) + + // Check returndata out-of-bounds error + if gt(add(sourceOffset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { + panic() + } + + copyActivePtrData(add(MEM_OFFSET_INNER(), dstOffset), sourceOffset, len) ip := add(ip, 1) } case 0x3F { // OP_EXTCODEHASH evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let addr := stackHead + let addr := accessStackHead(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -1761,52 +1741,48 @@ object "EvmEmulator" { case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := blockhash(stackHead) + stackHead := blockhash(accessStackHead(sp, stackHead)) ip := add(ip, 1) } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, coinbase(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, coinbase(), stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, timestamp(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, timestamp(), stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, number(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, number(), stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, prevrandao(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, prevrandao(), stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, gaslimit(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, gaslimit(), stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, chainid(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, chainid(), stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE evmGasLeft := chargeGas(evmGasLeft, 5) - sp, stackHead := pushStackItem(sp, selfbalance(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, selfbalance(), stackHead) ip := add(ip, 1) } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, basefee(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, basefee(), stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP @@ -1814,19 +1790,15 @@ object "EvmEmulator" { let _y - _y, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) + _y, sp, stackHead := popStackItem(sp, stackHead) ip := add(ip, 1) } case 0x51 { // OP_MLOAD evmGasLeft := chargeGas(evmGasLeft, 3) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let offset := stackHead + let offset := accessStackHead(sp, stackHead) - checkMemOverflowByOffset(offset, evmGasLeft) + checkMemIsAccessible(offset, 32) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) @@ -1839,11 +1811,11 @@ object "EvmEmulator" { let offset, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemOverflowByOffset(offset, evmGasLeft) + checkMemIsAccessible(offset, 32) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) @@ -1855,11 +1827,11 @@ object "EvmEmulator" { let offset, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemOverflowByOffset(offset, evmGasLeft) + checkMemIsAccessible(offset, 1) let expansionGas := expandMemory(add(offset, 1)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) @@ -1867,23 +1839,16 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0x54 { // OP_SLOAD - evmGasLeft := chargeGas(evmGasLeft, 100) - let key, value, isWarm - - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - key := stackHead - + let key := accessStackHead(sp, stackHead) let wasWarm := isSlotWarm(key) if iszero(wasWarm) { evmGasLeft := chargeGas(evmGasLeft, 2000) } - value := sload(key) + let value := sload(key) if iszero(wasWarm) { let _wasW, _orgV := warmSlot(key, value) @@ -1896,12 +1861,12 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 100) if isStatic { - revertWithGas(evmGasLeft) + panic() } let key, value, gasSpent - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -1909,7 +1874,7 @@ object "EvmEmulator" { { // 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); + // Im not sure if we need this before: require(gasLeft > GAS_CALL_STIPEND); // TODO let currentValue := sload(key) let wasWarm, originalValue := warmSlot(key, currentValue) @@ -1931,7 +1896,6 @@ object "EvmEmulator" { 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) @@ -1940,14 +1904,14 @@ object "EvmEmulator" { let counter - counter, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) + counter, sp, stackHead := popStackItem(sp, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST let nextOpcode := readIP(ip,maxAcceptablePos) if iszero(eq(nextOpcode, 0x5B)) { - revertWithGas(evmGasLeft) + panic() } // execute JUMPDEST immediately @@ -1959,7 +1923,7 @@ object "EvmEmulator" { let counter, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) counter, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) b, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -1971,9 +1935,9 @@ object "EvmEmulator" { ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST - let nextOpcode := readIP(ip,maxAcceptablePos) + let nextOpcode := readIP(ip, maxAcceptablePos) if iszero(eq(nextOpcode, 0x5B)) { - revertWithGas(evmGasLeft) + panic() } // execute JUMPDEST immediately @@ -1985,22 +1949,22 @@ object "EvmEmulator" { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), stackHead) } case 0x59 { // OP_MSIZE - evmGasLeft := chargeGas(evmGasLeft,2) + evmGasLeft := chargeGas(evmGasLeft, 2) let size size := mload(MEM_OFFSET()) - size := shl(5,size) - sp, stackHead := pushStackItem(sp,size, evmGasLeft, stackHead) + size := shl(5, size) + sp, stackHead := pushStackItem(sp, size, stackHead) ip := add(ip, 1) } case 0x5A { // OP_GAS evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, evmGasLeft, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5B { // OP_JUMPDEST @@ -2010,22 +1974,18 @@ object "EvmEmulator" { case 0x5C { // OP_TLOAD evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := tload(stackHead) + stackHead := tload(accessStackHead(sp, stackHead)) ip := add(ip, 1) } case 0x5D { // OP_TSTORE evmGasLeft := chargeGas(evmGasLeft, 100) if isStatic { - revertWithGas(evmGasLeft) + panic() } let key, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -2034,18 +1994,18 @@ object "EvmEmulator" { } case 0x5E { // OP_MCOPY let destOffset, offset, size - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkOverflow(destOffset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) - checkMemOverflowByOffset(add(destOffset, size), evmGasLeft) + checkMemIsAccessible(offset, size) + checkMemIsAccessible(destOffset, size) - expandMemory(add(destOffset, size)) - expandMemory(add(offset, size)) + { + let maxExpand := getMaxMemoryExpansionCost(offset, size, destOffset, size) + evmGasLeft := chargeGas(evmGasLeft, maxExpand) + } mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) ip := add(ip, 1) @@ -2055,300 +2015,300 @@ object "EvmEmulator" { let value := 0 - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 1) } case 0x60 { // OP_PUSH1 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,1) + let value := readBytes(ip, maxAcceptablePos, 1) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 1) } case 0x61 { // OP_PUSH2 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,2) + let value := readBytes(ip, maxAcceptablePos, 2) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 2) } case 0x62 { // OP_PUSH3 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,3) + let value := readBytes(ip, maxAcceptablePos, 3) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 3) } case 0x63 { // OP_PUSH4 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,4) + let value := readBytes(ip, maxAcceptablePos, 4) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 4) } case 0x64 { // OP_PUSH5 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,5) + let value := readBytes(ip, maxAcceptablePos, 5) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 5) } case 0x65 { // OP_PUSH6 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,6) + let value := readBytes(ip, maxAcceptablePos, 6) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 6) } case 0x66 { // OP_PUSH7 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,7) + let value := readBytes(ip, maxAcceptablePos, 7) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 7) } case 0x67 { // OP_PUSH8 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,8) + let value := readBytes(ip, maxAcceptablePos, 8) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 8) } case 0x68 { // OP_PUSH9 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,9) + let value := readBytes(ip, maxAcceptablePos, 9) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 9) } case 0x69 { // OP_PUSH10 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,10) + let value := readBytes(ip, maxAcceptablePos, 10) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 10) } case 0x6A { // OP_PUSH11 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,11) + let value := readBytes(ip, maxAcceptablePos, 11) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 11) } case 0x6B { // OP_PUSH12 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,12) + let value := readBytes(ip, maxAcceptablePos, 12) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 12) } case 0x6C { // OP_PUSH13 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,13) + let value := readBytes(ip, maxAcceptablePos, 13) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 13) } case 0x6D { // OP_PUSH14 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,14) + let value := readBytes(ip, maxAcceptablePos, 14) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 14) } case 0x6E { // OP_PUSH15 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,15) + let value := readBytes(ip, maxAcceptablePos, 15) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 15) } case 0x6F { // OP_PUSH16 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,16) + let value := readBytes(ip, maxAcceptablePos, 16) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 16) } case 0x70 { // OP_PUSH17 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,17) + let value := readBytes(ip, maxAcceptablePos, 17) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 17) } case 0x71 { // OP_PUSH18 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,18) + let value := readBytes(ip, maxAcceptablePos, 18) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 18) } case 0x72 { // OP_PUSH19 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,19) + let value := readBytes(ip, maxAcceptablePos, 19) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 19) } case 0x73 { // OP_PUSH20 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,20) + let value := readBytes(ip, maxAcceptablePos, 20) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 20) } case 0x74 { // OP_PUSH21 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,21) + let value := readBytes(ip, maxAcceptablePos, 21) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 21) } case 0x75 { // OP_PUSH22 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,22) + let value := readBytes(ip, maxAcceptablePos, 22) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 22) } case 0x76 { // OP_PUSH23 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,23) + let value := readBytes(ip, maxAcceptablePos, 23) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 23) } case 0x77 { // OP_PUSH24 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,24) + let value := readBytes(ip, maxAcceptablePos, 24) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 24) } case 0x78 { // OP_PUSH25 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,25) + let value := readBytes(ip, maxAcceptablePos, 25) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 25) } case 0x79 { // OP_PUSH26 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,26) + let value := readBytes(ip, maxAcceptablePos, 26) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 26) } case 0x7A { // OP_PUSH27 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,27) + let value := readBytes(ip, maxAcceptablePos, 27) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 27) } case 0x7B { // OP_PUSH28 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,28) + let value := readBytes(ip, maxAcceptablePos, 28) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 28) } case 0x7C { // OP_PUSH29 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,29) + let value := readBytes(ip, maxAcceptablePos, 29) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 29) } case 0x7D { // OP_PUSH30 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,30) + let value := readBytes(ip, maxAcceptablePos, 30) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 30) } case 0x7E { // OP_PUSH31 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,31) + let value := readBytes(ip, maxAcceptablePos, 31) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 31) } case 0x7F { // OP_PUSH32 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,32) + let value := readBytes(ip, maxAcceptablePos, 32) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 32) } case 0x80 { // OP_DUP1 evmGasLeft := chargeGas(evmGasLeft, 3) - sp, stackHead := pushStackItem(sp, stackHead, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, stackHead, stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 @@ -2479,16 +2439,15 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -2501,16 +2460,15 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -2526,17 +2484,17 @@ object "EvmEmulator" { } case 0xA2 { // OP_LOG2 evmGasLeft := chargeGas(evmGasLeft, 375) + if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 4) + popStackCheck(sp, 4) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -2555,16 +2513,15 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 5) + popStackCheck(sp, 5) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -2584,16 +2541,15 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 6) + popStackCheck(sp, 6) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -2628,14 +2584,13 @@ object "EvmEmulator" { case 0xF3 { // OP_RETURN let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) + checkMemIsAccessible(offset, size) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) returnLen := size @@ -2651,23 +2606,22 @@ object "EvmEmulator" { let result, addr evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) switch result - case 0 { sp, stackHead := pushStackItem(sp, 0, evmGasLeft, stackHead) } - default { sp, stackHead := pushStackItem(sp, addr, evmGasLeft, stackHead) } + case 0 { sp, stackHead := pushStackItem(sp, 0, stackHead) } + default { sp, stackHead := pushStackItem(sp, addr, stackHead) } ip := add(ip, 1) } case 0xFA { // OP_STATICCALL - evmGasLeft, sp, stackHead := performStaticCall(sp,evmGasLeft, stackHead) + evmGasLeft, sp, stackHead := performStaticCall(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0xFD { // OP_REVERT let offset,size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) // Don't check overflow here since previous checks are enough to ensure this is safe @@ -2685,7 +2639,6 @@ object "EvmEmulator" { } case 0xFE { // OP_INVALID evmGasLeft := 0 - revertWithGas(evmGasLeft) } // We explicitly add unused opcodes to optimize the jump table by compiler. @@ -3148,31 +3101,35 @@ object "EvmEmulator" { revert(0, 32) } + function panic() { + revert(0, 0) + } + function chargeGas(prevGas, toCharge) -> gasRemaining { if lt(prevGas, toCharge) { - revertWithGas(0) + panic() } gasRemaining := sub(prevGas, toCharge) } - function checkMemOverflowByOffset(offset, evmGasLeft) { - if gt(offset, MAX_POSSIBLE_MEM()) { - mstore(0, evmGasLeft) - revert(0, 32) + function checkMemIsAccessible(index, offset) { + checkOverflow(index, offset) + + if gt(add(index, offset), MAX_MEMORY_FRAME()) { + panic() } } - function checkMemOverflow(location, evmGasLeft) { + function checkMemOverflow(location) { if gt(location, MAX_MEMORY_FRAME()) { - mstore(0, evmGasLeft) - revert(0, 32) + panic() } } - function checkOverflow(data1, data2, evmGasLeft) { + function checkOverflow(data1, data2) { if lt(add(data1, data2), data2) { - revertWithGas(evmGasLeft) + panic() } } @@ -3432,7 +3389,7 @@ object "EvmEmulator" { let tempSp := sub(sp, mul(0x20, sub(position, 1))) if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } mstore(sp, oldStackHead) @@ -3445,17 +3402,17 @@ object "EvmEmulator" { let tempSp := sub(sp, mul(0x20, position)) if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } stackHead := mload(tempSp) mstore(tempSp, oldStackHead) } - function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { + function popStackItem(sp, oldStackHead) -> a, newSp, stackHead { // We can not return any error here, because it would break compatibility if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } a := oldStackHead @@ -3463,9 +3420,9 @@ object "EvmEmulator" { stackHead := mload(newSp) } - function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { + function pushStackItem(sp, item, oldStackHead) -> newSp, stackHead { if iszero(lt(sp, BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) + panic() } mstore(sp, oldStackHead) @@ -3485,18 +3442,26 @@ object "EvmEmulator" { newSp := add(sp, 0x20) } - function popStackCheck(sp, evmGasLeft, numInputs) { + function popStackCheck(sp, numInputs) { if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } } - function pushStackCheck(sp, evmGasLeft, numInputs) { + function pushStackCheck(sp, numInputs) { if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) + panic() } } + function accessStackHead(sp, stackHead) -> value { + if lt(sp, STACK_OFFSET()) { + panic() + } + + value := stackHead + } + //////////////////////////////////////////////////////////////// // EVM GAS MANAGER FUNCTIONALITY //////////////////////////////////////////////////////////////// @@ -3580,7 +3545,7 @@ object "EvmEmulator" { function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 7) + popStackCheck(oldSp, 7) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -3590,12 +3555,8 @@ object "EvmEmulator" { addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - - checkOverflow(argsOffset,argsSize, evmGasLeft) - checkOverflow(retOffset, retSize, evmGasLeft) - - checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) - checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) // static_gas = 0 // dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + positive_value_cost + value_to_empty_account_cost @@ -3619,7 +3580,7 @@ object "EvmEmulator" { } { - let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } @@ -3656,7 +3617,7 @@ object "EvmEmulator" { function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { let gasToPass,addr, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 6) + popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -3665,11 +3626,8 @@ object "EvmEmulator" { addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - checkOverflow(argsOffset,argsSize, evmGasLeft) - checkOverflow(retOffset, retSize, evmGasLeft) - - checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) - checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) let gasUsed := 100 if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -3677,7 +3635,7 @@ object "EvmEmulator" { } { - let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } @@ -3714,7 +3672,7 @@ object "EvmEmulator" { function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEvmGasLeft, sp, stackHead { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 6) + popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -3723,15 +3681,8 @@ object "EvmEmulator" { 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) - } + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) let gasUsed := 100 if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -3739,12 +3690,16 @@ object "EvmEmulator" { } { - let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } evmGasLeft := chargeGas(evmGasLeft, gasUsed) + if iszero(_isEVM(addr)) { + revertWithGas(evmGasLeft) + } + gasToPass := capGasForCall(evmGasLeft, gasToPass) _pushEVMFrame(gasToPass, isStatic) @@ -3831,7 +3786,7 @@ object "EvmEmulator" { } } - function getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) -> maxExpand { + function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> maxExpand { maxExpand := add(retOffset, retSize) switch lt(maxExpand, add(argsOffset, argsSize)) case 0 { @@ -4035,15 +3990,15 @@ object "EvmEmulator" { function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { _eraseReturndataPointer() - let gasForTheCall := capGasForCall(evmGasLeftOld,INF_PASS_GAS()) + let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) - if lt(selfbalance(),value) { + if lt(selfbalance(), value) { // TODO optimize revertWithGas(evmGasLeftOld) } - offset := add(MEM_OFFSET_INNER(), offset) + offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check - pushStackCheck(sp, evmGasLeftOld, 4) + pushStackCheck(sp, 4) sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) @@ -4109,20 +4064,19 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { - revertWithGas(evmGasLeft) // TODO review + panic() } let value, offset, size - popStackCheck(oldSp, evmGasLeft, 3) + popStackCheck(oldSp, 3) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { - revertWithGas(evmGasLeft) + revertWithGas(evmGasLeft) // TODO check } if gt(value, balance(address())) { @@ -4151,19 +4105,18 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGas, 32000) if isStatic { - revertWithGas(evmGasLeft) + panic() } let value, offset, size, salt - popStackCheck(oldSp, evmGasLeft, 4) + popStackCheck(oldSp, 4) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { revertWithGas(evmGasLeft) @@ -4228,36 +4181,6 @@ object "EvmEmulator" { $llvm_AlwaysInline_llvm$_copyRest(dest_end, 0, rest_len) } } - - function performExtCodeCopy(evmGas,oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { - evmGasLeft := chargeGas(evmGas, 100) - - let addr, dest, offset, len - popStackCheck(oldSp, evmGasLeft, 4) - addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - // 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 $llvm_NoInline_llvm$_simulate( isCallerEVM, @@ -4288,7 +4211,7 @@ object "EvmEmulator" { case 0x01 { // OP_ADD evmGasLeft := chargeGas(evmGasLeft, 3) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := add(a, stackHead) @@ -4298,7 +4221,7 @@ object "EvmEmulator" { case 0x02 { // OP_MUL evmGasLeft := chargeGas(evmGasLeft, 5) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := mul(a, stackHead) @@ -4307,7 +4230,7 @@ object "EvmEmulator" { case 0x03 { // OP_SUB evmGasLeft := chargeGas(evmGasLeft, 3) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := sub(a, stackHead) @@ -4317,7 +4240,7 @@ object "EvmEmulator" { case 0x04 { // OP_DIV evmGasLeft := chargeGas(evmGasLeft, 5) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := div(a, stackHead) @@ -4327,7 +4250,7 @@ object "EvmEmulator" { case 0x05 { // OP_SDIV evmGasLeft := chargeGas(evmGasLeft, 5) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := sdiv(a, stackHead) @@ -4338,7 +4261,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 5) let a - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := mod(a, stackHead) @@ -4348,7 +4271,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 5) let a - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := smod(a, stackHead) @@ -4359,7 +4282,7 @@ object "EvmEmulator" { let a, b, N - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) b, sp, N := popStackItemWithoutCheck(sp, stackHead) stackHead := addmod(a, b, N) @@ -4371,7 +4294,7 @@ object "EvmEmulator" { let a, b, N - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) b, sp, N := popStackItemWithoutCheck(sp, stackHead) @@ -4383,7 +4306,7 @@ object "EvmEmulator" { let a, exponent - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) stackHead := exp(a, exponent) @@ -4401,7 +4324,7 @@ object "EvmEmulator" { let b, x - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) b, sp, x := popStackItemWithoutCheck(sp, stackHead) stackHead := signextend(b, x) @@ -4412,7 +4335,7 @@ object "EvmEmulator" { let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := lt(a, b) @@ -4423,7 +4346,7 @@ object "EvmEmulator" { let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead:= gt(a, b) @@ -4434,7 +4357,7 @@ object "EvmEmulator" { let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := slt(a, b) @@ -4444,7 +4367,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := sgt(a, b) @@ -4454,7 +4377,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := eq(a, b) @@ -4463,10 +4386,7 @@ object "EvmEmulator" { case 0x15 { // OP_ISZERO evmGasLeft := chargeGas(evmGasLeft, 3) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - stackHead := iszero(stackHead) + stackHead := iszero(accessStackHead(sp, stackHead)) ip := add(ip, 1) } @@ -4474,7 +4394,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := and(a,b) @@ -4484,7 +4404,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := or(a,b) @@ -4494,7 +4414,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := xor(a, b) @@ -4503,11 +4423,7 @@ object "EvmEmulator" { case 0x19 { // OP_NOT evmGasLeft := chargeGas(evmGasLeft, 3) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := not(stackHead) + stackHead := not(accessStackHead(sp, stackHead)) ip := add(ip, 1) } @@ -4515,7 +4431,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let i, x - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) i, sp, x := popStackItemWithoutCheck(sp, stackHead) stackHead := byte(i, x) @@ -4525,7 +4441,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let shift, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) shift, sp, value := popStackItemWithoutCheck(sp, stackHead) stackHead := shl(shift, value) @@ -4535,7 +4451,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let shift, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) shift, sp, value := popStackItemWithoutCheck(sp, stackHead) stackHead := shr(shift, value) @@ -4545,7 +4461,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) let shift, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) shift, sp, value := popStackItemWithoutCheck(sp, stackHead) stackHead := sar(shift, value) @@ -4556,11 +4472,11 @@ object "EvmEmulator" { let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) + let keccak := keccak256(add(MEM_OFFSET_INNER(), offset), size) // When an offset is first accessed (either read or write), memory may trigger @@ -4576,17 +4492,13 @@ object "EvmEmulator" { case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, address(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, address(), stackHead) ip := add(ip, 1) } case 0x31 { // OP_BALANCE evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let addr := stackHead + let addr := accessStackHead(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -4600,36 +4512,32 @@ object "EvmEmulator" { case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, origin(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, origin(), stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, caller(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, caller(), stackHead) ip := add(ip, 1) } case 0x34 { // OP_CALLVALUE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, callvalue(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, callvalue(), stackHead) ip := add(ip, 1) } case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) - - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - stackHead := calldataload(stackHead) + stackHead := calldataload(accessStackHead(sp, stackHead)) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, calldatasize(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, calldatasize(), stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -4637,13 +4545,12 @@ object "EvmEmulator" { let destOffset, offset, size - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(destOffset, size, evmGasLeft) - checkMemOverflowByOffset(add(destOffset,size), evmGasLeft) + checkMemIsAccessible(destOffset, size) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -4658,52 +4565,49 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 2) let bytecodeLen := mload(BYTECODE_OFFSET()) - sp, stackHead := pushStackItem(sp, bytecodeLen, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, bytecodeLen, stackHead) ip := add(ip, 1) } case 0x39 { // OP_CODECOPY evmGasLeft := chargeGas(evmGasLeft, 3) - let dst, offset, len + let dstOffset, sourceOffset, len - popStackCheck(sp, evmGasLeft, 3) - dst, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + popStackCheck(sp, 3) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + sourceOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + checkMemIsAccessible(dstOffset, len) + // 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))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dstOffset, len))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - dst := add(dst, MEM_OFFSET_INNER()) - offset := add(add(offset, BYTECODE_OFFSET()), 32) + dstOffset := add(dstOffset, MEM_OFFSET_INNER()) + sourceOffset := add(add(sourceOffset, BYTECODE_OFFSET()), 32) - checkOverflow(dst,len, evmGasLeft) - checkOverflow(offset,len, evmGasLeft) - checkMemOverflow(add(dst, len), evmGasLeft) + checkOverflow(sourceOffset, len) // Check bytecode overflow - if gt(add(offset, len), sub(MEM_OFFSET(), 1)) { - revertWithGas(evmGasLeft) + if gt(add(sourceOffset, len), sub(MEM_OFFSET(), 1)) { + panic() } - $llvm_AlwaysInline_llvm$_memcpy(dst, offset, len) + $llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, len) ip := add(ip, 1) } case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, gasprice(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, gasprice(), stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - let addr := stackHead + let addr := accessStackHead(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -4717,47 +4621,76 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY - evmGasLeft, sp, stackHead := performExtCodeCopy(evmGasLeft, sp, stackHead) + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr, dest, offset, len + popStackCheck(sp, 4) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + + checkMemIsAccessible(dest, len) + + // 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()))) + } + ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) - sp, stackHead := pushStackItem(sp, rdz, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, rdz, stackHead) ip := add(ip, 1) } case 0x3E { // OP_RETURNDATACOPY evmGasLeft := chargeGas(evmGasLeft, 3) - let dest, offset, len - popStackCheck(sp, evmGasLeft, 3) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + let dstOffset, sourceOffset, len + popStackCheck(sp, 3) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + sourceOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset,len, evmGasLeft) - if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { - revertWithGas(evmGasLeft) - } + checkMemIsAccessible(dstOffset, len) // 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))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dstOffset, len))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - copyActivePtrData(add(MEM_OFFSET_INNER(), dest), offset, len) + checkOverflow(sourceOffset, len) + + // Check returndata out-of-bounds error + if gt(add(sourceOffset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { + panic() + } + + copyActivePtrData(add(MEM_OFFSET_INNER(), dstOffset), sourceOffset, len) ip := add(ip, 1) } case 0x3F { // OP_EXTCODEHASH evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let addr := stackHead + let addr := accessStackHead(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -4774,52 +4707,48 @@ object "EvmEmulator" { case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := blockhash(stackHead) + stackHead := blockhash(accessStackHead(sp, stackHead)) ip := add(ip, 1) } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, coinbase(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, coinbase(), stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, timestamp(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, timestamp(), stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, number(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, number(), stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, prevrandao(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, prevrandao(), stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, gaslimit(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, gaslimit(), stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, chainid(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, chainid(), stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE evmGasLeft := chargeGas(evmGasLeft, 5) - sp, stackHead := pushStackItem(sp, selfbalance(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, selfbalance(), stackHead) ip := add(ip, 1) } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, basefee(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, basefee(), stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP @@ -4827,19 +4756,15 @@ object "EvmEmulator" { let _y - _y, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) + _y, sp, stackHead := popStackItem(sp, stackHead) ip := add(ip, 1) } case 0x51 { // OP_MLOAD evmGasLeft := chargeGas(evmGasLeft, 3) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } + let offset := accessStackHead(sp, stackHead) - let offset := stackHead - - checkMemOverflowByOffset(offset, evmGasLeft) + checkMemIsAccessible(offset, 32) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) @@ -4852,11 +4777,11 @@ object "EvmEmulator" { let offset, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemOverflowByOffset(offset, evmGasLeft) + checkMemIsAccessible(offset, 32) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) @@ -4868,11 +4793,11 @@ object "EvmEmulator" { let offset, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemOverflowByOffset(offset, evmGasLeft) + checkMemIsAccessible(offset, 1) let expansionGas := expandMemory(add(offset, 1)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) @@ -4880,23 +4805,16 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0x54 { // OP_SLOAD - evmGasLeft := chargeGas(evmGasLeft, 100) - let key, value, isWarm - - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - key := stackHead - + let key := accessStackHead(sp, stackHead) let wasWarm := isSlotWarm(key) if iszero(wasWarm) { evmGasLeft := chargeGas(evmGasLeft, 2000) } - value := sload(key) + let value := sload(key) if iszero(wasWarm) { let _wasW, _orgV := warmSlot(key, value) @@ -4909,12 +4827,12 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 100) if isStatic { - revertWithGas(evmGasLeft) + panic() } let key, value, gasSpent - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -4922,7 +4840,7 @@ object "EvmEmulator" { { // 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); + // Im not sure if we need this before: require(gasLeft > GAS_CALL_STIPEND); // TODO let currentValue := sload(key) let wasWarm, originalValue := warmSlot(key, currentValue) @@ -4944,7 +4862,6 @@ object "EvmEmulator" { 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) @@ -4953,14 +4870,14 @@ object "EvmEmulator" { let counter - counter, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) + counter, sp, stackHead := popStackItem(sp, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST let nextOpcode := readIP(ip,maxAcceptablePos) if iszero(eq(nextOpcode, 0x5B)) { - revertWithGas(evmGasLeft) + panic() } // execute JUMPDEST immediately @@ -4972,7 +4889,7 @@ object "EvmEmulator" { let counter, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) counter, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) b, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -4984,9 +4901,9 @@ object "EvmEmulator" { ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST - let nextOpcode := readIP(ip,maxAcceptablePos) + let nextOpcode := readIP(ip, maxAcceptablePos) if iszero(eq(nextOpcode, 0x5B)) { - revertWithGas(evmGasLeft) + panic() } // execute JUMPDEST immediately @@ -4998,22 +4915,22 @@ object "EvmEmulator" { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), stackHead) } case 0x59 { // OP_MSIZE - evmGasLeft := chargeGas(evmGasLeft,2) + evmGasLeft := chargeGas(evmGasLeft, 2) let size size := mload(MEM_OFFSET()) - size := shl(5,size) - sp, stackHead := pushStackItem(sp,size, evmGasLeft, stackHead) + size := shl(5, size) + sp, stackHead := pushStackItem(sp, size, stackHead) ip := add(ip, 1) } case 0x5A { // OP_GAS evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, evmGasLeft, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5B { // OP_JUMPDEST @@ -5023,22 +4940,18 @@ object "EvmEmulator" { case 0x5C { // OP_TLOAD evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := tload(stackHead) + stackHead := tload(accessStackHead(sp, stackHead)) ip := add(ip, 1) } case 0x5D { // OP_TSTORE evmGasLeft := chargeGas(evmGasLeft, 100) if isStatic { - revertWithGas(evmGasLeft) + panic() } let key, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -5047,18 +4960,18 @@ object "EvmEmulator" { } case 0x5E { // OP_MCOPY let destOffset, offset, size - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkOverflow(destOffset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) - checkMemOverflowByOffset(add(destOffset, size), evmGasLeft) + checkMemIsAccessible(offset, size) + checkMemIsAccessible(destOffset, size) - expandMemory(add(destOffset, size)) - expandMemory(add(offset, size)) + { + let maxExpand := getMaxMemoryExpansionCost(offset, size, destOffset, size) + evmGasLeft := chargeGas(evmGasLeft, maxExpand) + } mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) ip := add(ip, 1) @@ -5068,300 +4981,300 @@ object "EvmEmulator" { let value := 0 - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 1) } case 0x60 { // OP_PUSH1 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,1) + let value := readBytes(ip, maxAcceptablePos, 1) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 1) } case 0x61 { // OP_PUSH2 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,2) + let value := readBytes(ip, maxAcceptablePos, 2) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 2) } case 0x62 { // OP_PUSH3 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,3) + let value := readBytes(ip, maxAcceptablePos, 3) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 3) } case 0x63 { // OP_PUSH4 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,4) + let value := readBytes(ip, maxAcceptablePos, 4) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 4) } case 0x64 { // OP_PUSH5 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,5) + let value := readBytes(ip, maxAcceptablePos, 5) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 5) } case 0x65 { // OP_PUSH6 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,6) + let value := readBytes(ip, maxAcceptablePos, 6) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 6) } case 0x66 { // OP_PUSH7 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,7) + let value := readBytes(ip, maxAcceptablePos, 7) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 7) } case 0x67 { // OP_PUSH8 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,8) + let value := readBytes(ip, maxAcceptablePos, 8) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 8) } case 0x68 { // OP_PUSH9 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,9) + let value := readBytes(ip, maxAcceptablePos, 9) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 9) } case 0x69 { // OP_PUSH10 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,10) + let value := readBytes(ip, maxAcceptablePos, 10) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 10) } case 0x6A { // OP_PUSH11 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,11) + let value := readBytes(ip, maxAcceptablePos, 11) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 11) } case 0x6B { // OP_PUSH12 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,12) + let value := readBytes(ip, maxAcceptablePos, 12) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 12) } case 0x6C { // OP_PUSH13 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,13) + let value := readBytes(ip, maxAcceptablePos, 13) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 13) } case 0x6D { // OP_PUSH14 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,14) + let value := readBytes(ip, maxAcceptablePos, 14) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 14) } case 0x6E { // OP_PUSH15 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,15) + let value := readBytes(ip, maxAcceptablePos, 15) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 15) } case 0x6F { // OP_PUSH16 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,16) + let value := readBytes(ip, maxAcceptablePos, 16) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 16) } case 0x70 { // OP_PUSH17 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,17) + let value := readBytes(ip, maxAcceptablePos, 17) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 17) } case 0x71 { // OP_PUSH18 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,18) + let value := readBytes(ip, maxAcceptablePos, 18) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 18) } case 0x72 { // OP_PUSH19 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,19) + let value := readBytes(ip, maxAcceptablePos, 19) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 19) } case 0x73 { // OP_PUSH20 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,20) + let value := readBytes(ip, maxAcceptablePos, 20) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 20) } case 0x74 { // OP_PUSH21 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,21) + let value := readBytes(ip, maxAcceptablePos, 21) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 21) } case 0x75 { // OP_PUSH22 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,22) + let value := readBytes(ip, maxAcceptablePos, 22) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 22) } case 0x76 { // OP_PUSH23 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,23) + let value := readBytes(ip, maxAcceptablePos, 23) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 23) } case 0x77 { // OP_PUSH24 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,24) + let value := readBytes(ip, maxAcceptablePos, 24) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 24) } case 0x78 { // OP_PUSH25 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,25) + let value := readBytes(ip, maxAcceptablePos, 25) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 25) } case 0x79 { // OP_PUSH26 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,26) + let value := readBytes(ip, maxAcceptablePos, 26) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 26) } case 0x7A { // OP_PUSH27 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,27) + let value := readBytes(ip, maxAcceptablePos, 27) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 27) } case 0x7B { // OP_PUSH28 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,28) + let value := readBytes(ip, maxAcceptablePos, 28) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 28) } case 0x7C { // OP_PUSH29 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,29) + let value := readBytes(ip, maxAcceptablePos, 29) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 29) } case 0x7D { // OP_PUSH30 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,30) + let value := readBytes(ip, maxAcceptablePos, 30) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 30) } case 0x7E { // OP_PUSH31 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,31) + let value := readBytes(ip, maxAcceptablePos, 31) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 31) } case 0x7F { // OP_PUSH32 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,32) + let value := readBytes(ip, maxAcceptablePos, 32) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 32) } case 0x80 { // OP_DUP1 evmGasLeft := chargeGas(evmGasLeft, 3) - sp, stackHead := pushStackItem(sp, stackHead, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, stackHead, stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 @@ -5492,16 +5405,15 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -5514,16 +5426,15 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -5539,17 +5450,17 @@ object "EvmEmulator" { } case 0xA2 { // OP_LOG2 evmGasLeft := chargeGas(evmGasLeft, 375) + if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 4) + popStackCheck(sp, 4) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -5568,16 +5479,15 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 5) + popStackCheck(sp, 5) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -5597,16 +5507,15 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 6) + popStackCheck(sp, 6) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -5641,14 +5550,13 @@ object "EvmEmulator" { case 0xF3 { // OP_RETURN let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) + checkMemIsAccessible(offset, size) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) returnLen := size @@ -5664,23 +5572,22 @@ object "EvmEmulator" { let result, addr evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) switch result - case 0 { sp, stackHead := pushStackItem(sp, 0, evmGasLeft, stackHead) } - default { sp, stackHead := pushStackItem(sp, addr, evmGasLeft, stackHead) } + case 0 { sp, stackHead := pushStackItem(sp, 0, stackHead) } + default { sp, stackHead := pushStackItem(sp, addr, stackHead) } ip := add(ip, 1) } case 0xFA { // OP_STATICCALL - evmGasLeft, sp, stackHead := performStaticCall(sp,evmGasLeft, stackHead) + evmGasLeft, sp, stackHead := performStaticCall(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0xFD { // OP_REVERT let offset,size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) // Don't check overflow here since previous checks are enough to ensure this is safe @@ -5698,7 +5605,6 @@ object "EvmEmulator" { } case 0xFE { // OP_INVALID evmGasLeft := 0 - revertWithGas(evmGasLeft) } // We explicitly add unused opcodes to optimize the jump table by compiler. @@ -6044,7 +5950,7 @@ object "EvmEmulator" { if eq(isCallerEVM, 1) { // Includes gas returnOffset := sub(returnOffset, 32) - checkOverflow(returnLen, 32, evmGasLeft) + checkOverflow(returnLen, 32) returnLen := add(returnLen, 32) mstore(returnOffset, evmGasLeft) diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index b9ed6d2b3..321db4556 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -110,7 +110,7 @@ object "EvmEmulator" { if eq(isCallerEVM, 1) { // Includes gas returnOffset := sub(returnOffset, 32) - checkOverflow(returnLen, 32, evmGasLeft) + checkOverflow(returnLen, 32) returnLen := add(returnLen, 32) mstore(returnOffset, evmGasLeft) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index cc011da2f..b728f1254 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -85,31 +85,35 @@ function revertWithGas(evmGasLeft) { revert(0, 32) } +function panic() { + revert(0, 0) +} + function chargeGas(prevGas, toCharge) -> gasRemaining { if lt(prevGas, toCharge) { - revertWithGas(0) + panic() } gasRemaining := sub(prevGas, toCharge) } -function checkMemOverflowByOffset(offset, evmGasLeft) { - if gt(offset, MAX_POSSIBLE_MEM()) { - mstore(0, evmGasLeft) - revert(0, 32) +function checkMemIsAccessible(index, offset) { + checkOverflow(index, offset) + + if gt(add(index, offset), MAX_MEMORY_FRAME()) { + panic() } } -function checkMemOverflow(location, evmGasLeft) { +function checkMemOverflow(location) { if gt(location, MAX_MEMORY_FRAME()) { - mstore(0, evmGasLeft) - revert(0, 32) + panic() } } -function checkOverflow(data1, data2, evmGasLeft) { +function checkOverflow(data1, data2) { if lt(add(data1, data2), data2) { - revertWithGas(evmGasLeft) + panic() } } @@ -369,7 +373,7 @@ function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, let tempSp := sub(sp, mul(0x20, sub(position, 1))) if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } mstore(sp, oldStackHead) @@ -382,17 +386,17 @@ function swapStackItem(sp, evmGas, position, oldStackHead) -> evmGasLeft, stack let tempSp := sub(sp, mul(0x20, position)) if lt(tempSp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } stackHead := mload(tempSp) mstore(tempSp, oldStackHead) } -function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { +function popStackItem(sp, oldStackHead) -> a, newSp, stackHead { // We can not return any error here, because it would break compatibility if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } a := oldStackHead @@ -400,9 +404,9 @@ function popStackItem(sp, evmGasLeft, oldStackHead) -> a, newSp, stackHead { stackHead := mload(newSp) } -function pushStackItem(sp, item, evmGasLeft, oldStackHead) -> newSp, stackHead { +function pushStackItem(sp, item, oldStackHead) -> newSp, stackHead { if iszero(lt(sp, BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) + panic() } mstore(sp, oldStackHead) @@ -422,18 +426,26 @@ function pushStackItemWithoutCheck(sp, item, oldStackHead) -> newSp, stackHead { newSp := add(sp, 0x20) } -function popStackCheck(sp, evmGasLeft, numInputs) { +function popStackCheck(sp, numInputs) { if lt(sub(sp, mul(0x20, sub(numInputs, 1))), STACK_OFFSET()) { - revertWithGas(evmGasLeft) + panic() } } -function pushStackCheck(sp, evmGasLeft, numInputs) { +function pushStackCheck(sp, numInputs) { if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { - revertWithGas(evmGasLeft) + panic() } } +function accessStackHead(sp, stackHead) -> value { + if lt(sp, STACK_OFFSET()) { + panic() + } + + value := stackHead +} + //////////////////////////////////////////////////////////////// // EVM GAS MANAGER FUNCTIONALITY //////////////////////////////////////////////////////////////// @@ -517,7 +529,7 @@ function consumeEvmFrame() -> passGas, isStatic, callerEVM { function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 7) + popStackCheck(oldSp, 7) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -527,12 +539,8 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - - checkOverflow(argsOffset,argsSize, evmGasLeft) - checkOverflow(retOffset, retSize, evmGasLeft) - - checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) - checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) // static_gas = 0 // dynamic_gas = memory_expansion_cost + code_execution_cost + address_access_cost + positive_value_cost + value_to_empty_account_cost @@ -556,7 +564,7 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe } { - let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } @@ -593,7 +601,7 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { let gasToPass,addr, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 6) + popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -602,11 +610,8 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - checkOverflow(argsOffset,argsSize, evmGasLeft) - checkOverflow(retOffset, retSize, evmGasLeft) - - checkMemOverflowByOffset(add(argsOffset, argsSize), evmGasLeft) - checkMemOverflowByOffset(add(retOffset, retSize), evmGasLeft) + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) let gasUsed := 100 if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -614,7 +619,7 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s } { - let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } @@ -651,7 +656,7 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEvmGasLeft, sp, stackHead { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize - popStackCheck(oldSp, evmGasLeft, 6) + popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -660,15 +665,8 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEv 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) - } + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) let gasUsed := 100 if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -676,12 +674,16 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEv } { - let maxExpand := getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) + let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) gasUsed := add(gasUsed, maxExpand) } evmGasLeft := chargeGas(evmGasLeft, gasUsed) + if iszero(_isEVM(addr)) { + revertWithGas(evmGasLeft) + } + gasToPass := capGasForCall(evmGasLeft, gasToPass) _pushEVMFrame(gasToPass, isStatic) @@ -768,7 +770,7 @@ function capGasForCall(evmGasLeft,oldGasToPass) -> gasToPass { } } -function getMemoryExpansionCostForCall(retOffset, retSize, argsOffset, argsSize) -> maxExpand { +function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> maxExpand { maxExpand := add(retOffset, retSize) switch lt(maxExpand, add(argsOffset, argsSize)) case 0 { @@ -972,15 +974,15 @@ function _fetchConstructorReturnGas() -> gasLeft { function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { _eraseReturndataPointer() - let gasForTheCall := capGasForCall(evmGasLeftOld,INF_PASS_GAS()) + let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) - if lt(selfbalance(),value) { + if lt(selfbalance(), value) { // TODO optimize revertWithGas(evmGasLeftOld) } - offset := add(MEM_OFFSET_INNER(), offset) + offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check - pushStackCheck(sp, evmGasLeftOld, 4) + pushStackCheck(sp, 4) sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) @@ -1046,20 +1048,19 @@ function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, s evmGasLeft := chargeGas(evmGas, 32000) if isStatic { - revertWithGas(evmGasLeft) // TODO review + panic() } let value, offset, size - popStackCheck(oldSp, evmGasLeft, 3) + popStackCheck(oldSp, 3) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { - revertWithGas(evmGasLeft) + revertWithGas(evmGasLeft) // TODO check } if gt(value, balance(address())) { @@ -1088,19 +1089,18 @@ function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp evmGasLeft := chargeGas(evmGas, 32000) if isStatic { - revertWithGas(evmGasLeft) + panic() } let value, offset, size, salt - popStackCheck(oldSp, evmGasLeft, 4) + popStackCheck(oldSp, 4) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { revertWithGas(evmGasLeft) @@ -1164,34 +1164,4 @@ function $llvm_AlwaysInline_llvm$_memsetToZero(dest,len) { if rest_len { $llvm_AlwaysInline_llvm$_copyRest(dest_end, 0, rest_len) } -} - -function performExtCodeCopy(evmGas,oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { - evmGasLeft := chargeGas(evmGas, 100) - - let addr, dest, offset, len - popStackCheck(oldSp, evmGasLeft, 4) - addr, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - // 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()))) - } } \ No newline at end of file diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index f1531a82d..907fce9ea 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -18,7 +18,7 @@ for { } true { } { case 0x01 { // OP_ADD evmGasLeft := chargeGas(evmGasLeft, 3) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := add(a, stackHead) @@ -28,7 +28,7 @@ for { } true { } { case 0x02 { // OP_MUL evmGasLeft := chargeGas(evmGasLeft, 5) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := mul(a, stackHead) @@ -37,7 +37,7 @@ for { } true { } { case 0x03 { // OP_SUB evmGasLeft := chargeGas(evmGasLeft, 3) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := sub(a, stackHead) @@ -47,7 +47,7 @@ for { } true { } { case 0x04 { // OP_DIV evmGasLeft := chargeGas(evmGasLeft, 5) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := div(a, stackHead) @@ -57,7 +57,7 @@ for { } true { } { case 0x05 { // OP_SDIV evmGasLeft := chargeGas(evmGasLeft, 5) - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) let a a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := sdiv(a, stackHead) @@ -68,7 +68,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 5) let a - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := mod(a, stackHead) @@ -78,7 +78,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 5) let a - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) stackHead := smod(a, stackHead) @@ -89,7 +89,7 @@ for { } true { } { let a, b, N - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) b, sp, N := popStackItemWithoutCheck(sp, stackHead) stackHead := addmod(a, b, N) @@ -101,7 +101,7 @@ for { } true { } { let a, b, N - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) a, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) b, sp, N := popStackItemWithoutCheck(sp, stackHead) @@ -113,7 +113,7 @@ for { } true { } { let a, exponent - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) stackHead := exp(a, exponent) @@ -131,7 +131,7 @@ for { } true { } { let b, x - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) b, sp, x := popStackItemWithoutCheck(sp, stackHead) stackHead := signextend(b, x) @@ -142,7 +142,7 @@ for { } true { } { let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := lt(a, b) @@ -153,7 +153,7 @@ for { } true { } { let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead:= gt(a, b) @@ -164,7 +164,7 @@ for { } true { } { let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := slt(a, b) @@ -174,7 +174,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := sgt(a, b) @@ -184,7 +184,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := eq(a, b) @@ -193,10 +193,7 @@ for { } true { } { case 0x15 { // OP_ISZERO evmGasLeft := chargeGas(evmGasLeft, 3) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - stackHead := iszero(stackHead) + stackHead := iszero(accessStackHead(sp, stackHead)) ip := add(ip, 1) } @@ -204,7 +201,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := and(a,b) @@ -214,7 +211,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := or(a,b) @@ -224,7 +221,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) let a, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) a, sp, b := popStackItemWithoutCheck(sp, stackHead) stackHead := xor(a, b) @@ -233,11 +230,7 @@ for { } true { } { case 0x19 { // OP_NOT evmGasLeft := chargeGas(evmGasLeft, 3) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := not(stackHead) + stackHead := not(accessStackHead(sp, stackHead)) ip := add(ip, 1) } @@ -245,7 +238,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) let i, x - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) i, sp, x := popStackItemWithoutCheck(sp, stackHead) stackHead := byte(i, x) @@ -255,7 +248,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) let shift, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) shift, sp, value := popStackItemWithoutCheck(sp, stackHead) stackHead := shl(shift, value) @@ -265,7 +258,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) let shift, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) shift, sp, value := popStackItemWithoutCheck(sp, stackHead) stackHead := shr(shift, value) @@ -275,7 +268,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) let shift, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) shift, sp, value := popStackItemWithoutCheck(sp, stackHead) stackHead := sar(shift, value) @@ -286,11 +279,11 @@ for { } true { } { let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) + let keccak := keccak256(add(MEM_OFFSET_INNER(), offset), size) // When an offset is first accessed (either read or write), memory may trigger @@ -306,17 +299,13 @@ for { } true { } { case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, address(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, address(), stackHead) ip := add(ip, 1) } case 0x31 { // OP_BALANCE evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let addr := stackHead + let addr := accessStackHead(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -330,36 +319,32 @@ for { } true { } { case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, origin(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, origin(), stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, caller(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, caller(), stackHead) ip := add(ip, 1) } case 0x34 { // OP_CALLVALUE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, callvalue(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, callvalue(), stackHead) ip := add(ip, 1) } case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) - - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - stackHead := calldataload(stackHead) + stackHead := calldataload(accessStackHead(sp, stackHead)) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, calldatasize(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, calldatasize(), stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -367,13 +352,12 @@ for { } true { } { let destOffset, offset, size - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(destOffset, size, evmGasLeft) - checkMemOverflowByOffset(add(destOffset,size), evmGasLeft) + checkMemIsAccessible(destOffset, size) // dynamicGas = 3 * minimum_word_size + memory_expansion_cost // minimum_word_size = (size + 31) / 32 @@ -388,52 +372,49 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 2) let bytecodeLen := mload(BYTECODE_OFFSET()) - sp, stackHead := pushStackItem(sp, bytecodeLen, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, bytecodeLen, stackHead) ip := add(ip, 1) } case 0x39 { // OP_CODECOPY evmGasLeft := chargeGas(evmGasLeft, 3) - let dst, offset, len + let dstOffset, sourceOffset, len - popStackCheck(sp, evmGasLeft, 3) - dst, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + popStackCheck(sp, 3) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + sourceOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + checkMemIsAccessible(dstOffset, len) + // 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))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dstOffset, len))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - dst := add(dst, MEM_OFFSET_INNER()) - offset := add(add(offset, BYTECODE_OFFSET()), 32) + dstOffset := add(dstOffset, MEM_OFFSET_INNER()) + sourceOffset := add(add(sourceOffset, BYTECODE_OFFSET()), 32) - checkOverflow(dst,len, evmGasLeft) - checkOverflow(offset,len, evmGasLeft) - checkMemOverflow(add(dst, len), evmGasLeft) + checkOverflow(sourceOffset, len) // Check bytecode overflow - if gt(add(offset, len), sub(MEM_OFFSET(), 1)) { - revertWithGas(evmGasLeft) + if gt(add(sourceOffset, len), sub(MEM_OFFSET(), 1)) { + panic() } - $llvm_AlwaysInline_llvm$_memcpy(dst, offset, len) + $llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, len) ip := add(ip, 1) } case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, gasprice(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, gasprice(), stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - let addr := stackHead + let addr := accessStackHead(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -447,47 +428,76 @@ for { } true { } { ip := add(ip, 1) } case 0x3C { // OP_EXTCODECOPY - evmGasLeft, sp, stackHead := performExtCodeCopy(evmGasLeft, sp, stackHead) + evmGasLeft := chargeGas(evmGasLeft, 100) + + let addr, dest, offset, len + popStackCheck(sp, 4) + addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + + checkMemIsAccessible(dest, len) + + // 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()))) + } + ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) let rdz := mload(LAST_RETURNDATA_SIZE_OFFSET()) - sp, stackHead := pushStackItem(sp, rdz, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, rdz, stackHead) ip := add(ip, 1) } case 0x3E { // OP_RETURNDATACOPY evmGasLeft := chargeGas(evmGasLeft, 3) - let dest, offset, len - popStackCheck(sp, evmGasLeft, 3) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + let dstOffset, sourceOffset, len + popStackCheck(sp, 3) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + sourceOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset,len, evmGasLeft) - if gt(add(offset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { - revertWithGas(evmGasLeft) - } + checkMemIsAccessible(dstOffset, len) // 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))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dstOffset, len))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - copyActivePtrData(add(MEM_OFFSET_INNER(), dest), offset, len) + checkOverflow(sourceOffset, len) + + // Check returndata out-of-bounds error + if gt(add(sourceOffset, len), mload(LAST_RETURNDATA_SIZE_OFFSET())) { + panic() + } + + copyActivePtrData(add(MEM_OFFSET_INNER(), dstOffset), sourceOffset, len) ip := add(ip, 1) } case 0x3F { // OP_EXTCODEHASH evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - let addr := stackHead + let addr := accessStackHead(sp, stackHead) addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -504,52 +514,48 @@ for { } true { } { case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := blockhash(stackHead) + stackHead := blockhash(accessStackHead(sp, stackHead)) ip := add(ip, 1) } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, coinbase(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, coinbase(), stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, timestamp(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, timestamp(), stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, number(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, number(), stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, prevrandao(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, prevrandao(), stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, gaslimit(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, gaslimit(), stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, chainid(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, chainid(), stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE evmGasLeft := chargeGas(evmGasLeft, 5) - sp, stackHead := pushStackItem(sp, selfbalance(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, selfbalance(), stackHead) ip := add(ip, 1) } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, basefee(), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, basefee(), stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP @@ -557,19 +563,15 @@ for { } true { } { let _y - _y, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) + _y, sp, stackHead := popStackItem(sp, stackHead) ip := add(ip, 1) } case 0x51 { // OP_MLOAD evmGasLeft := chargeGas(evmGasLeft, 3) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } + let offset := accessStackHead(sp, stackHead) - let offset := stackHead - - checkMemOverflowByOffset(offset, evmGasLeft) + checkMemIsAccessible(offset, 32) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) @@ -582,11 +584,11 @@ for { } true { } { let offset, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemOverflowByOffset(offset, evmGasLeft) + checkMemIsAccessible(offset, 32) let expansionGas := expandMemory(add(offset, 32)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) @@ -598,11 +600,11 @@ for { } true { } { let offset, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemOverflowByOffset(offset, evmGasLeft) + checkMemIsAccessible(offset, 1) let expansionGas := expandMemory(add(offset, 1)) evmGasLeft := chargeGas(evmGasLeft, expansionGas) @@ -610,23 +612,16 @@ for { } true { } { ip := add(ip, 1) } case 0x54 { // OP_SLOAD - evmGasLeft := chargeGas(evmGasLeft, 100) - let key, value, isWarm - - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - key := stackHead - + let key := accessStackHead(sp, stackHead) let wasWarm := isSlotWarm(key) if iszero(wasWarm) { evmGasLeft := chargeGas(evmGasLeft, 2000) } - value := sload(key) + let value := sload(key) if iszero(wasWarm) { let _wasW, _orgV := warmSlot(key, value) @@ -639,12 +634,12 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 100) if isStatic { - revertWithGas(evmGasLeft) + panic() } let key, value, gasSpent - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -652,7 +647,7 @@ for { } true { } { { // 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); + // Im not sure if we need this before: require(gasLeft > GAS_CALL_STIPEND); // TODO let currentValue := sload(key) let wasWarm, originalValue := warmSlot(key, currentValue) @@ -674,7 +669,6 @@ for { } true { } { 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) @@ -683,14 +677,14 @@ for { } true { } { let counter - counter, sp, stackHead := popStackItem(sp, evmGasLeft, stackHead) + counter, sp, stackHead := popStackItem(sp, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST let nextOpcode := readIP(ip,maxAcceptablePos) if iszero(eq(nextOpcode, 0x5B)) { - revertWithGas(evmGasLeft) + panic() } // execute JUMPDEST immediately @@ -702,7 +696,7 @@ for { } true { } { let counter, b - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) counter, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) b, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -714,9 +708,9 @@ for { } true { } { ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST - let nextOpcode := readIP(ip,maxAcceptablePos) + let nextOpcode := readIP(ip, maxAcceptablePos) if iszero(eq(nextOpcode, 0x5B)) { - revertWithGas(evmGasLeft) + panic() } // execute JUMPDEST immediately @@ -728,22 +722,22 @@ for { } true { } { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), stackHead) } case 0x59 { // OP_MSIZE - evmGasLeft := chargeGas(evmGasLeft,2) + evmGasLeft := chargeGas(evmGasLeft, 2) let size size := mload(MEM_OFFSET()) - size := shl(5,size) - sp, stackHead := pushStackItem(sp,size, evmGasLeft, stackHead) + size := shl(5, size) + sp, stackHead := pushStackItem(sp, size, stackHead) ip := add(ip, 1) } case 0x5A { // OP_GAS evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, evmGasLeft, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0x5B { // OP_JUMPDEST @@ -753,22 +747,18 @@ for { } true { } { case 0x5C { // OP_TLOAD evmGasLeft := chargeGas(evmGasLeft, 100) - if lt(sp, STACK_OFFSET()) { - revertWithGas(evmGasLeft) - } - - stackHead := tload(stackHead) + stackHead := tload(accessStackHead(sp, stackHead)) ip := add(ip, 1) } case 0x5D { // OP_TSTORE evmGasLeft := chargeGas(evmGasLeft, 100) if isStatic { - revertWithGas(evmGasLeft) + panic() } let key, value - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -777,18 +767,18 @@ for { } true { } { } case 0x5E { // OP_MCOPY let destOffset, offset, size - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkOverflow(destOffset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) - checkMemOverflowByOffset(add(destOffset, size), evmGasLeft) + checkMemIsAccessible(offset, size) + checkMemIsAccessible(destOffset, size) - expandMemory(add(destOffset, size)) - expandMemory(add(offset, size)) + { + let maxExpand := getMaxMemoryExpansionCost(offset, size, destOffset, size) + evmGasLeft := chargeGas(evmGasLeft, maxExpand) + } mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) ip := add(ip, 1) @@ -798,300 +788,300 @@ for { } true { } { let value := 0 - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 1) } case 0x60 { // OP_PUSH1 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,1) + let value := readBytes(ip, maxAcceptablePos, 1) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 1) } case 0x61 { // OP_PUSH2 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,2) + let value := readBytes(ip, maxAcceptablePos, 2) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 2) } case 0x62 { // OP_PUSH3 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,3) + let value := readBytes(ip, maxAcceptablePos, 3) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 3) } case 0x63 { // OP_PUSH4 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,4) + let value := readBytes(ip, maxAcceptablePos, 4) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 4) } case 0x64 { // OP_PUSH5 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,5) + let value := readBytes(ip, maxAcceptablePos, 5) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 5) } case 0x65 { // OP_PUSH6 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,6) + let value := readBytes(ip, maxAcceptablePos, 6) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 6) } case 0x66 { // OP_PUSH7 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,7) + let value := readBytes(ip, maxAcceptablePos, 7) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 7) } case 0x67 { // OP_PUSH8 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,8) + let value := readBytes(ip, maxAcceptablePos, 8) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 8) } case 0x68 { // OP_PUSH9 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,9) + let value := readBytes(ip, maxAcceptablePos, 9) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 9) } case 0x69 { // OP_PUSH10 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,10) + let value := readBytes(ip, maxAcceptablePos, 10) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 10) } case 0x6A { // OP_PUSH11 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,11) + let value := readBytes(ip, maxAcceptablePos, 11) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 11) } case 0x6B { // OP_PUSH12 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,12) + let value := readBytes(ip, maxAcceptablePos, 12) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 12) } case 0x6C { // OP_PUSH13 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,13) + let value := readBytes(ip, maxAcceptablePos, 13) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 13) } case 0x6D { // OP_PUSH14 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,14) + let value := readBytes(ip, maxAcceptablePos, 14) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 14) } case 0x6E { // OP_PUSH15 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,15) + let value := readBytes(ip, maxAcceptablePos, 15) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 15) } case 0x6F { // OP_PUSH16 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,16) + let value := readBytes(ip, maxAcceptablePos, 16) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 16) } case 0x70 { // OP_PUSH17 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,17) + let value := readBytes(ip, maxAcceptablePos, 17) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 17) } case 0x71 { // OP_PUSH18 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,18) + let value := readBytes(ip, maxAcceptablePos, 18) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 18) } case 0x72 { // OP_PUSH19 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,19) + let value := readBytes(ip, maxAcceptablePos, 19) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 19) } case 0x73 { // OP_PUSH20 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,20) + let value := readBytes(ip, maxAcceptablePos, 20) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 20) } case 0x74 { // OP_PUSH21 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,21) + let value := readBytes(ip, maxAcceptablePos, 21) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 21) } case 0x75 { // OP_PUSH22 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,22) + let value := readBytes(ip, maxAcceptablePos, 22) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 22) } case 0x76 { // OP_PUSH23 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,23) + let value := readBytes(ip, maxAcceptablePos, 23) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 23) } case 0x77 { // OP_PUSH24 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,24) + let value := readBytes(ip, maxAcceptablePos, 24) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 24) } case 0x78 { // OP_PUSH25 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,25) + let value := readBytes(ip, maxAcceptablePos, 25) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 25) } case 0x79 { // OP_PUSH26 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,26) + let value := readBytes(ip, maxAcceptablePos, 26) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 26) } case 0x7A { // OP_PUSH27 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,27) + let value := readBytes(ip, maxAcceptablePos, 27) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 27) } case 0x7B { // OP_PUSH28 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,28) + let value := readBytes(ip, maxAcceptablePos, 28) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 28) } case 0x7C { // OP_PUSH29 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,29) + let value := readBytes(ip, maxAcceptablePos, 29) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 29) } case 0x7D { // OP_PUSH30 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,30) + let value := readBytes(ip, maxAcceptablePos, 30) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 30) } case 0x7E { // OP_PUSH31 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,31) + let value := readBytes(ip, maxAcceptablePos, 31) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 31) } case 0x7F { // OP_PUSH32 evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip,maxAcceptablePos,32) + let value := readBytes(ip, maxAcceptablePos, 32) - sp, stackHead := pushStackItem(sp, value, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 32) } case 0x80 { // OP_DUP1 evmGasLeft := chargeGas(evmGasLeft, 3) - sp, stackHead := pushStackItem(sp, stackHead, evmGasLeft, stackHead) + sp, stackHead := pushStackItem(sp, stackHead, stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 @@ -1222,16 +1212,15 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -1244,16 +1233,15 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 3) + popStackCheck(sp, 3) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -1269,17 +1257,17 @@ for { } true { } { } case 0xA2 { // OP_LOG2 evmGasLeft := chargeGas(evmGasLeft, 375) + if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 4) + popStackCheck(sp, 4) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -1298,16 +1286,15 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 5) + popStackCheck(sp, 5) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -1327,16 +1314,15 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 375) if isStatic { - revertWithGas(evmGasLeft) + panic() } let offset, size - popStackCheck(sp, evmGasLeft, 6) + popStackCheck(sp, 6) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) @@ -1371,14 +1357,13 @@ for { } true { } { case 0xF3 { // OP_RETURN let offset, size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) + checkMemIsAccessible(offset, size) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) returnLen := size @@ -1394,23 +1379,22 @@ for { } true { } { let result, addr evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) switch result - case 0 { sp, stackHead := pushStackItem(sp, 0, evmGasLeft, stackHead) } - default { sp, stackHead := pushStackItem(sp, addr, evmGasLeft, stackHead) } + case 0 { sp, stackHead := pushStackItem(sp, 0, stackHead) } + default { sp, stackHead := pushStackItem(sp, addr, stackHead) } ip := add(ip, 1) } case 0xFA { // OP_STATICCALL - evmGasLeft, sp, stackHead := performStaticCall(sp,evmGasLeft, stackHead) + evmGasLeft, sp, stackHead := performStaticCall(sp, evmGasLeft, stackHead) ip := add(ip, 1) } case 0xFD { // OP_REVERT let offset,size - popStackCheck(sp, evmGasLeft, 2) + popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkOverflow(offset, size, evmGasLeft) - checkMemOverflowByOffset(add(offset, size), evmGasLeft) + checkMemIsAccessible(offset, size) evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) // Don't check overflow here since previous checks are enough to ensure this is safe @@ -1428,7 +1412,6 @@ for { } true { } { } case 0xFE { // OP_INVALID evmGasLeft := 0 - revertWithGas(evmGasLeft) } // We explicitly add unused opcodes to optimize the jump table by compiler. From 14bdfb04c951d3d84024c5990a30b757ea2e27bc Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 24 Oct 2024 21:09:56 +0200 Subject: [PATCH 094/183] fix(EVM): Fix panics in create/create2 (#975) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 60 +++++++------------ .../evm-emulator/EvmEmulator.template.yul | 8 ++- .../EvmEmulatorFunctions.template.yul | 26 +++----- 4 files changed, 35 insertions(+), 63 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 057e59112..4389b1f2e 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cc15cda7e95291300368963dc790e59bea406b834bc2fe487c8ff05c31b", - "sourceCodeHash": "0x7efddc39cf95e293f4e08683cda2726cc6541de60f517f0150c894bef0336342" + "bytecodeHash": "0x01000c9fd914e077c0a0927ebb0180de1df3beb78e31060ff90fb188793970fc", + "sourceCodeHash": "0x71e661624d0783e70d9321bbea17446160fe5661c3f9c2f62c7b8d0283eedcc4" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 96d3ffb7a..5fcd9fb9c 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -10,8 +10,12 @@ object "EvmEmulator" { loadCalldataIntoActivePtr() let size := getActivePtrDataSize() - mstore(bytecodeLengthOffset, size) + if gt(size, MAX_POSSIBLE_BYTECODE()) { + panic() + } + + mstore(bytecodeLengthOffset, size) copyActivePtrData(bytecodeOffset, 0, size) } @@ -282,7 +286,7 @@ object "EvmEmulator" { _len := codeLen } - returndatacopy(dest, add(32,_offset), _len) + returndatacopy(dest, add(32, _offset), _len) } // Returns the length of the bytecode. @@ -812,7 +816,7 @@ object "EvmEmulator" { } } - function capGasForCall(evmGasLeft,oldGasToPass) -> gasToPass { + function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 gasToPass := oldGasToPass if gt(oldGasToPass, maxGasToPass) { @@ -1026,10 +1030,6 @@ object "EvmEmulator" { let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) - if lt(selfbalance(), value) { // TODO optimize - revertWithGas(evmGasLeftOld) - } - offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check pushStackCheck(sp, 4) @@ -1109,12 +1109,8 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) - if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { - revertWithGas(evmGasLeft) // TODO check - } - - if gt(value, balance(address())) { - revertWithGas(evmGasLeft) + if gt(size, MAX_POSSIBLE_BYTECODE()) { + panic() } // dynamicGas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost @@ -1152,12 +1148,8 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) - if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { - revertWithGas(evmGasLeft) - } - - if gt(value, balance(address())) { - revertWithGas(evmGasLeft) + if gt(size, MAX_POSSIBLE_BYTECODE()) { + panic() } // dynamicGas = init_code_cost + hash_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost @@ -1170,7 +1162,7 @@ object "EvmEmulator" { shr(2, add(size, 31)) )) - result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt, stackHead) + result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, true, salt, stackHead) } //////////////////////////////////////////////////////////////// @@ -3248,7 +3240,7 @@ object "EvmEmulator" { _len := codeLen } - returndatacopy(dest, add(32,_offset), _len) + returndatacopy(dest, add(32, _offset), _len) } // Returns the length of the bytecode. @@ -3778,7 +3770,7 @@ object "EvmEmulator" { } } - function capGasForCall(evmGasLeft,oldGasToPass) -> gasToPass { + function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 gasToPass := oldGasToPass if gt(oldGasToPass, maxGasToPass) { @@ -3992,10 +3984,6 @@ object "EvmEmulator" { let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) - if lt(selfbalance(), value) { // TODO optimize - revertWithGas(evmGasLeftOld) - } - offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check pushStackCheck(sp, 4) @@ -4075,12 +4063,8 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) - if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { - revertWithGas(evmGasLeft) // TODO check - } - - if gt(value, balance(address())) { - revertWithGas(evmGasLeft) + if gt(size, MAX_POSSIBLE_BYTECODE()) { + panic() } // dynamicGas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost @@ -4118,12 +4102,8 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) - if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { - revertWithGas(evmGasLeft) - } - - if gt(value, balance(address())) { - revertWithGas(evmGasLeft) + if gt(size, MAX_POSSIBLE_BYTECODE()) { + panic() } // dynamicGas = init_code_cost + hash_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost @@ -4136,7 +4116,7 @@ object "EvmEmulator" { shr(2, add(size, 31)) )) - result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt, stackHead) + result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, true, salt, stackHead) } //////////////////////////////////////////////////////////////// @@ -5968,7 +5948,7 @@ object "EvmEmulator" { isStatic := getIsStaticFromCallFlags() } - // First, copy the contract's bytecode to be executed into tEdhe `BYTECODE_OFFSET` + // First, copy the contract's bytecode to be executed into the `BYTECODE_OFFSET` // segment of memory. getDeployedBytecode() diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index 321db4556..e6eee5b35 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -10,8 +10,12 @@ object "EvmEmulator" { loadCalldataIntoActivePtr() let size := getActivePtrDataSize() - mstore(bytecodeLengthOffset, size) + if gt(size, MAX_POSSIBLE_BYTECODE()) { + panic() + } + + mstore(bytecodeLengthOffset, size) copyActivePtrData(bytecodeOffset, 0, size) } @@ -128,7 +132,7 @@ object "EvmEmulator" { isStatic := getIsStaticFromCallFlags() } - // First, copy the contract's bytecode to be executed into tEdhe `BYTECODE_OFFSET` + // First, copy the contract's bytecode to be executed into the `BYTECODE_OFFSET` // segment of memory. getDeployedBytecode() diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index b728f1254..c852d5d65 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -232,7 +232,7 @@ function _fetchDeployedCodeWithDest(addr, _offset, _len, dest) -> codeLen { _len := codeLen } - returndatacopy(dest, add(32,_offset), _len) + returndatacopy(dest, add(32, _offset), _len) } // Returns the length of the bytecode. @@ -762,7 +762,7 @@ function _getZkEVMGasForCall(_evmGas, addr) -> zkevmGas { } } -function capGasForCall(evmGasLeft,oldGasToPass) -> gasToPass { +function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 gasToPass := oldGasToPass if gt(oldGasToPass, maxGasToPass) { @@ -976,10 +976,6 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) - if lt(selfbalance(), value) { // TODO optimize - revertWithGas(evmGasLeftOld) - } - offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check pushStackCheck(sp, 4) @@ -1059,12 +1055,8 @@ function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, s checkMemIsAccessible(offset, size) - if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { - revertWithGas(evmGasLeft) // TODO check - } - - if gt(value, balance(address())) { - revertWithGas(evmGasLeft) + if gt(size, MAX_POSSIBLE_BYTECODE()) { + panic() } // dynamicGas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost @@ -1102,12 +1094,8 @@ function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp checkMemIsAccessible(offset, size) - if gt(size, mul(2, MAX_POSSIBLE_BYTECODE())) { - revertWithGas(evmGasLeft) - } - - if gt(value, balance(address())) { - revertWithGas(evmGasLeft) + if gt(size, MAX_POSSIBLE_BYTECODE()) { + panic() } // dynamicGas = init_code_cost + hash_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost @@ -1120,7 +1108,7 @@ function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp shr(2, add(size, 31)) )) - result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft,true,salt, stackHead) + result, evmGasLeft, addr, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, true, salt, stackHead) } //////////////////////////////////////////////////////////////// From 6dca1d49987940de60e9295699884520a973d919 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 24 Oct 2024 21:23:11 +0200 Subject: [PATCH 095/183] Simplify create flow --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 50 +++++++------------ .../EvmEmulatorFunctions.template.yul | 25 ++++------ 3 files changed, 29 insertions(+), 50 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 4389b1f2e..7f5ae10eb 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000c9fd914e077c0a0927ebb0180de1df3beb78e31060ff90fb188793970fc", - "sourceCodeHash": "0x71e661624d0783e70d9321bbea17446160fe5661c3f9c2f62c7b8d0283eedcc4" + "bytecodeHash": "0x01000c99d9b4bc1e53bba6f8448fc76980eae8db3b67005a193457f94ad6583d", + "sourceCodeHash": "0x33accfd8544792a19689bcf9ca44bd80bb2028f964e327cdea28c27e9cd41ff9" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 5fcd9fb9c..b9ff8b73b 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1032,11 +1032,10 @@ object "EvmEmulator" { offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check - pushStackCheck(sp, 4) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) + mstore(0x20, mload(sub(offset, 0x80)) + mstore(0x40, mload(sub(offset, 0x60)) + mstore(0x60, mload(sub(offset, 0x40)) + mstore(0x80, mload(sub(offset, 0x20)) _pushEVMFrame(gasForTheCall, false) @@ -1081,17 +1080,11 @@ object "EvmEmulator" { let gasUsed := sub(gasForTheCall, gasLeft) evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - let back - - // skipping check since we pushed exactly 4 items earlier - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x20), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x40), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x60), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x80), back) + // moving memory slots back + mstore(sub(offset, 0x80), mload(0x20)) + mstore(sub(offset, 0x60), mload(0x40)) + mstore(sub(offset, 0x40), mload(0x60)) + mstore(sub(offset, 0x20), mload(0x80)) } function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { @@ -3986,11 +3979,10 @@ object "EvmEmulator" { offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check - pushStackCheck(sp, 4) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) + mstore(0x20, mload(sub(offset, 0x80)) + mstore(0x40, mload(sub(offset, 0x60)) + mstore(0x60, mload(sub(offset, 0x40)) + mstore(0x80, mload(sub(offset, 0x20)) _pushEVMFrame(gasForTheCall, false) @@ -4035,17 +4027,11 @@ object "EvmEmulator" { let gasUsed := sub(gasForTheCall, gasLeft) evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - let back - - // skipping check since we pushed exactly 4 items earlier - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x20), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x40), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x60), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x80), back) + // moving memory slots back + mstore(sub(offset, 0x80), mload(0x20)) + mstore(sub(offset, 0x60), mload(0x40)) + mstore(sub(offset, 0x40), mload(0x60)) + mstore(sub(offset, 0x20), mload(0x80)) } function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index c852d5d65..a750fe7a3 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -978,11 +978,10 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check - pushStackCheck(sp, 4) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) + mstore(0x20, mload(sub(offset, 0x80)) + mstore(0x40, mload(sub(offset, 0x60)) + mstore(0x60, mload(sub(offset, 0x40)) + mstore(0x80, mload(sub(offset, 0x20)) _pushEVMFrame(gasForTheCall, false) @@ -1027,17 +1026,11 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO let gasUsed := sub(gasForTheCall, gasLeft) evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - let back - - // skipping check since we pushed exactly 4 items earlier - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x20), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x40), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x60), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x80), back) + // moving memory slots back + mstore(sub(offset, 0x80), mload(0x20)) + mstore(sub(offset, 0x60), mload(0x40)) + mstore(sub(offset, 0x40), mload(0x60)) + mstore(sub(offset, 0x20), mload(0x80)) } function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { From b4cfe5719ecd2a3dae6c2588cca4ccae04146238 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 24 Oct 2024 22:52:05 +0200 Subject: [PATCH 096/183] fix(EVM): Increase deployment nonce for EVM contracts even if creation failed for some reason (#976) --- system-contracts/SystemContractsHashes.json | 24 ++++++++--------- .../contracts/ContractDeployer.sol | 27 +++++++++++-------- system-contracts/contracts/EvmEmulator.yul | 18 +++++++++++++ .../contracts/abstract/SystemContractBase.sol | 4 +-- .../EvmEmulatorFunctions.template.yul | 9 +++++++ 5 files changed, 57 insertions(+), 25 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 7f5ae10eb..a15b60501 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -24,15 +24,15 @@ "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013f4563482d39692847cc181b307598310ae4f1e8200c5cb607d64540e0", + "bytecodeHash": "0x0100013ffa100e6cdf59d3f25ae78d832cd1feffbf0ebe22af08d90986097a5d", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010005d96d65df3e365c610e98b2b1e891b0a9171ccd79672c925754a1916bfb", - "sourceCodeHash": "0x7b99c6e8362654f9242079f1b664fe540ac3460547b773649f3e104c79b181a2" + "bytecodeHash": "0x01000607e7d5e1f44f9dc674cbdcbd5e69c951b25962d2fc6dea517804998de6", + "sourceCodeHash": "0x0f0c934d3358d0173d855a4369698a8c2f92f34575cfd04fec3341997d5449a7" }, { "contractName": "Create2Factory", @@ -66,49 +66,49 @@ "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000c1f7b2fefcf367b8c3a52debb615512bec8c9f768d2f18a3e864a4db6a", + "bytecodeHash": "0x010000c1d21b617f9bfe5e54df06ecefbb4777e0da3d8c6c23bbc10fb8234ed2", "sourceCodeHash": "0xeb83e3a2ea2f50b93122363b8dd56fbcfe821d11723d849eecbde3d6af1147de" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010002656691523f71be5e405f3ee49da893d16ce72787d5eeda7bd10c30bcb8", + "bytecodeHash": "0x0100026581914e835a621a69f53930a4c01380a7215ec525c2a0fdd421d0a226", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f3a6bb6fc63f2beefcfea0a33bade2cd6d943c78b8cc540126e6c89564", + "bytecodeHash": "0x010000f3236c6465720a9ed7e62139ab585fbc03736c6a2fde4775911c9ba9eb", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x010000598d4353beeea44dccfede2563de16f446c19c7ba7a417170ce353b295", + "bytecodeHash": "0x0100005947b1d73fa00f1f900b1763c769cb5509d11912153fdc4c952b8bc218", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cf091013c3fec019ce0ac2f3b54a578b2d8b9ff92bb708e4f6bbb4afa9", + "bytecodeHash": "0x010000cf060faf52ba4c9517d70710995e65e14ab74a246e2f5a58a0dbebeafc", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041b2cad46dfa6de19275af9f1e87924f8d03c5f1a9d8b8349d521d55c1", + "bytecodeHash": "0x01000041fcc8bf42926b7204852d1e6ead584091a7dad67f0f6ffaf65e674d2a", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c5cf3b0a9b74992e48334f871f44d88205077933f932193367ee6fd259", + "bytecodeHash": "0x010001c569017612e96a242865c78116d801c320f13a9bdfa0ad7efb206dce3a", "sourceCodeHash": "0xc5ce25a94e3b510183635dd2fe0152dbcaa705bc8802fb3a4390253b5af3aa0a" }, { @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000c99d9b4bc1e53bba6f8448fc76980eae8db3b67005a193457f94ad6583d", - "sourceCodeHash": "0x33accfd8544792a19689bcf9ca44bd80bb2028f964e327cdea28c27e9cd41ff9" + "bytecodeHash": "0x01000ca1c43f4e691b71df9d101b037ff4aab19463a61b1509fa9b2a2a30eeae", + "sourceCodeHash": "0x03856b047632115de2ce6fd064d0b45723183b14674e105ad6b64d399671a21f" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 7199cd379..47cbb9c8f 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -179,20 +179,29 @@ 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); address newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); - _evmDeployOnAddress(newAddress, _initCode); + + // If the method is called by an EVM contract, then we need to increase deployment + // nonce for a contract even if contract creation actually failed + if (SystemContractHelper.isSystemCall() && ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender)) { + // EVM emulator provides infinite gas + try this.evmDeployOnAddress{value: msg.value}(newAddress, _initCode) {} catch { + newAddress = address(0); + } + } else { + this.evmDeployOnAddress{value: msg.value}(newAddress, _initCode); + } + return newAddress; } + function evmDeployOnAddress(address _newAddress, bytes calldata _initCode) external payable onlySelf { + _evmDeployOnAddress(_newAddress, _initCode); + } + /// @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 @@ -499,10 +508,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } 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); - uint256 value = msg.value; // 1. Transfer the balance to the new address on the constructor call. if (value > 0) { diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index b9ff8b73b..42f343f54 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1051,6 +1051,7 @@ object "EvmEmulator" { result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) + addr := mload(0) } @@ -1064,6 +1065,14 @@ object "EvmEmulator" { result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) + + if iszero(result) { + // This error should never happen + revert(0, 0) + } + + addr := mload(0) + result := iszero(iszero(addr)) } addr := mload(0) @@ -3998,6 +4007,7 @@ object "EvmEmulator" { result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) + addr := mload(0) } @@ -4011,6 +4021,14 @@ object "EvmEmulator" { result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) + + if iszero(result) { + // This error should never happen + revert(0, 0) + } + + addr := mload(0) + result := iszero(iszero(addr)) } addr := mload(0) diff --git a/system-contracts/contracts/abstract/SystemContractBase.sol b/system-contracts/contracts/abstract/SystemContractBase.sol index 89966a576..bcbc8b64e 100644 --- a/system-contracts/contracts/abstract/SystemContractBase.sol +++ b/system-contracts/contracts/abstract/SystemContractBase.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.20; import {SystemContractHelper} from "../libraries/SystemContractHelper.sol"; -import {BOOTLOADER_FORMAL_ADDRESS, FORCE_DEPLOYER} from "../Constants.sol"; -import {SystemCallFlagRequired, Unauthorized, CallerMustBeSystemContract, CallerMustBeBootloader, CallerMustBeForceDeployer} from "../SystemContractErrors.sol"; +import {BOOTLOADER_FORMAL_ADDRESS, FORCE_DEPLOYER, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "../Constants.sol"; +import {SystemCallFlagRequired, Unauthorized, CallerMustBeSystemContract, CallerMustBeBootloader, CallerMustBeForceDeployer, CallerMustBeEvmContract} from "../SystemContractErrors.sol"; /** * @author Matter Labs diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index a750fe7a3..9f9f297fe 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -997,6 +997,7 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) + addr := mload(0) } @@ -1010,6 +1011,14 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) + + if iszero(result) { + // This error should never happen + revert(0, 0) + } + + addr := mload(0) + result := iszero(iszero(addr)) } addr := mload(0) From 6ff7adcae47ea5ebf008aca8ad24d5f441b70205 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 25 Oct 2024 00:17:26 +0200 Subject: [PATCH 097/183] fix(EVM): Fix semantic tests (#977) --- system-contracts/SystemContractsHashes.json | 8 +- .../contracts/ContractDeployer.sol | 28 ++++--- system-contracts/contracts/EvmEmulator.yul | 76 +++++++++---------- .../EvmEmulatorFunctions.template.yul | 38 +++++----- 4 files changed, 80 insertions(+), 70 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index a15b60501..a7fbbd777 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": "0x01000607e7d5e1f44f9dc674cbdcbd5e69c951b25962d2fc6dea517804998de6", - "sourceCodeHash": "0x0f0c934d3358d0173d855a4369698a8c2f92f34575cfd04fec3341997d5449a7" + "bytecodeHash": "0x0100062f3a64baacbc8bfa773c162913940f5e4efe70f87b2bb919c52e92b3d2", + "sourceCodeHash": "0xd26f48108304f2dcde3c85bb6add5095e9241f70b4fef03bff4b37bdad159fed" }, { "contractName": "Create2Factory", @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000ca1c43f4e691b71df9d101b037ff4aab19463a61b1509fa9b2a2a30eeae", - "sourceCodeHash": "0x03856b047632115de2ce6fd064d0b45723183b14674e105ad6b64d399671a21f" + "bytecodeHash": "0x01000cd9299d4a01997c340dc652d8467be23821446ce01fc89f9cb92f6b17ae", + "sourceCodeHash": "0x72a51372b295914998e75d36df5f4f8d834e1eab797765839823e39b1e32c64d" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 47cbb9c8f..15c74806a 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -177,6 +177,12 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } function createEVM(bytes calldata _initCode) external payable override returns (address) { + // TODO only for semantic tests? + uint256 deploymentNonce = NONCE_HOLDER_SYSTEM_CONTRACT.getDeploymentNonce(msg.sender); + if ((msg.sender != tx.origin) && deploymentNonce == 0) { + NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); + } + // 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 @@ -188,18 +194,20 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { // nonce for a contract even if contract creation actually failed if (SystemContractHelper.isSystemCall() && ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender)) { // EVM emulator provides infinite gas - try this.evmDeployOnAddress{value: msg.value}(newAddress, _initCode) {} catch { + try this.evmDeployOnAddress{value: msg.value}(msg.sender, newAddress, _initCode) {} catch { newAddress = address(0); } } else { - this.evmDeployOnAddress{value: msg.value}(newAddress, _initCode); + this.evmDeployOnAddress{value: msg.value}(msg.sender, newAddress, _initCode); } + //_evmDeployOnAddress(newAddress, _initCode); + return newAddress; } - function evmDeployOnAddress(address _newAddress, bytes calldata _initCode) external payable onlySelf { - _evmDeployOnAddress(_newAddress, _initCode); + function evmDeployOnAddress(address _sender, address _newAddress, bytes calldata _initCode) external payable onlySelf { + _evmDeployOnAddress(_sender, _newAddress, _initCode); } /// @notice Deploys an EVM contract using address derivation of EVM's `CREATE2` opcode @@ -213,7 +221,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { bytes32 bytecodeHash = EfficientCall.keccak(_initCode); address newAddress = Utils.getNewAddressCreate2EVM(msg.sender, _salt, bytecodeHash); - _evmDeployOnAddress(newAddress, _initCode); + _evmDeployOnAddress(msg.sender, newAddress, _initCode); return newAddress; } @@ -375,7 +383,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _performDeployOnAddress(_bytecodeHash, _newAddress, _aaVersion, _input, true); } - function _evmDeployOnAddress(address _newAddress, bytes calldata _initCode) internal { + function _evmDeployOnAddress(address _sender, address _newAddress, bytes calldata _initCode) internal { if (_getAllowedBytecodeTypesMode() != AllowedBytecodeTypes.EraVmAndEVM) { revert EVMEmulationNotSupported(); } @@ -383,7 +391,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); + _performDeployOnAddressEVM(_sender, _newAddress, AccountAbstractionVersion.None, _initCode); } /// @notice Deploy a certain bytecode on the address. @@ -417,10 +425,12 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } /// @notice Deploy a certain bytecode on the address. + /// @param _sender TODO /// @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 _sender, address _newAddress, AccountAbstractionVersion _aaVersion, bytes calldata _input @@ -435,7 +445,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(_newAddress); // When constructing they just get the intrepeter bytecode hash in consutrcting mode - _constructEVMContract(msg.sender, _newAddress, _input); + _constructEVMContract(_sender, _newAddress, _input); } /// @notice Check that bytecode hash is marked as known on the `KnownCodeStorage` system contracts @@ -532,7 +542,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _gas: uint32(gasleft()), _address: _newAddress, _data: _input, - _whoToMimic: msg.sender, + _whoToMimic: _sender, _isConstructor: true, _isSystem: false }); diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 42f343f54..bc70d33af 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -140,7 +140,8 @@ object "EvmEmulator" { } function panic() { - revert(0, 0) + mstore(0, 0) + revert(0, 32) } function chargeGas(prevGas, toCharge) -> gasRemaining { @@ -786,7 +787,7 @@ object "EvmEmulator" { // zkEVM native let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() - success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, 0, 0) + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) @@ -1032,10 +1033,11 @@ object "EvmEmulator" { offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check - mstore(0x20, mload(sub(offset, 0x80)) - mstore(0x40, mload(sub(offset, 0x60)) - mstore(0x60, mload(sub(offset, 0x40)) - mstore(0x80, mload(sub(offset, 0x20)) + pushStackCheck(sp, 4) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) _pushEVMFrame(gasForTheCall, false) @@ -1051,7 +1053,6 @@ object "EvmEmulator" { result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) - addr := mload(0) } @@ -1065,14 +1066,6 @@ object "EvmEmulator" { result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) - - if iszero(result) { - // This error should never happen - revert(0, 0) - } - - addr := mload(0) - result := iszero(iszero(addr)) } addr := mload(0) @@ -1090,10 +1083,17 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) // moving memory slots back - mstore(sub(offset, 0x80), mload(0x20)) - mstore(sub(offset, 0x60), mload(0x40)) - mstore(sub(offset, 0x40), mload(0x60)) - mstore(sub(offset, 0x20), mload(0x80)) + let back + + // skipping check since we pushed exactly 4 items earlier + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x20), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x40), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x60), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x80), back) } function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { @@ -3096,7 +3096,8 @@ object "EvmEmulator" { } function panic() { - revert(0, 0) + mstore(0, 0) + revert(0, 32) } function chargeGas(prevGas, toCharge) -> gasRemaining { @@ -3742,7 +3743,7 @@ object "EvmEmulator" { // zkEVM native let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() - success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, 0, 0) + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) @@ -3988,10 +3989,11 @@ object "EvmEmulator" { offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check - mstore(0x20, mload(sub(offset, 0x80)) - mstore(0x40, mload(sub(offset, 0x60)) - mstore(0x60, mload(sub(offset, 0x40)) - mstore(0x80, mload(sub(offset, 0x20)) + pushStackCheck(sp, 4) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) _pushEVMFrame(gasForTheCall, false) @@ -4007,7 +4009,6 @@ object "EvmEmulator" { result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) - addr := mload(0) } @@ -4021,14 +4022,6 @@ object "EvmEmulator" { result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) - - if iszero(result) { - // This error should never happen - revert(0, 0) - } - - addr := mload(0) - result := iszero(iszero(addr)) } addr := mload(0) @@ -4046,10 +4039,17 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) // moving memory slots back - mstore(sub(offset, 0x80), mload(0x20)) - mstore(sub(offset, 0x60), mload(0x40)) - mstore(sub(offset, 0x40), mload(0x60)) - mstore(sub(offset, 0x20), mload(0x80)) + let back + + // skipping check since we pushed exactly 4 items earlier + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x20), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x40), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x60), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x80), back) } function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 9f9f297fe..c3288c33e 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -86,7 +86,8 @@ function revertWithGas(evmGasLeft) { } function panic() { - revert(0, 0) + mstore(0, 0) + revert(0, 32) } function chargeGas(prevGas, toCharge) -> gasRemaining { @@ -732,7 +733,7 @@ function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, re // zkEVM native let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) let zkEvmGasBefore := gas() - success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, 0, 0) + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) @@ -978,10 +979,11 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check - mstore(0x20, mload(sub(offset, 0x80)) - mstore(0x40, mload(sub(offset, 0x60)) - mstore(0x60, mload(sub(offset, 0x40)) - mstore(0x80, mload(sub(offset, 0x20)) + pushStackCheck(sp, 4) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) + sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) _pushEVMFrame(gasForTheCall, false) @@ -997,7 +999,6 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x64), add(size, 0x64), 0, 32) - addr := mload(0) } @@ -1011,14 +1012,6 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO result := call(gas(), DEPLOYER_SYSTEM_CONTRACT(), value, sub(offset, 0x44), add(size, 0x44), 0, 32) - - if iszero(result) { - // This error should never happen - revert(0, 0) - } - - addr := mload(0) - result := iszero(iszero(addr)) } addr := mload(0) @@ -1036,10 +1029,17 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) // moving memory slots back - mstore(sub(offset, 0x80), mload(0x20)) - mstore(sub(offset, 0x60), mload(0x40)) - mstore(sub(offset, 0x40), mload(0x60)) - mstore(sub(offset, 0x20), mload(0x80)) + let back + + // skipping check since we pushed exactly 4 items earlier + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x20), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x40), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x60), back) + back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + mstore(sub(offset, 0x80), back) } function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { From a3305ee596a18602d0a2771d2e9e63bba5a9990f Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 25 Oct 2024 17:14:35 +0200 Subject: [PATCH 098/183] fix(EVM): Prepare fixed CREATE implementation (#993) --- system-contracts/SystemContractsHashes.json | 38 ++--- .../contracts/ContractDeployer.sol | 82 +++++++--- system-contracts/contracts/DefaultAccount.sol | 8 +- system-contracts/contracts/EvmEmulator.yul | 152 +++++++++++++++--- .../contracts/abstract/SystemContractBase.sol | 9 ++ .../libraries/SystemContractHelper.sol | 9 +- .../EvmEmulatorFunctions.template.yul | 76 +++++++-- 7 files changed, 297 insertions(+), 77 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index a7fbbd777..5996afe39 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,50 +3,50 @@ "contractName": "AccountCodeStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x010000779387ba87caebefbef966dc263054f8950a3120e6c3605445a215429c", + "bytecodeHash": "0x010000774aa1c7c082646986a5c0b076334728bc55ca9a8f206cdcf2f7b9bbb5", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f12f4e0198d02d5aaa39395041ffa928cabe89341d9e05ac9f2eb6b5fb", + "bytecodeHash": "0x010006f1aabdf55b55fdbbe0f255f75266faeb82d8f447d506918a994db2efcc", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x01000047ae25b732df64265d8fdb4935aa05b26448c35376e55d450cecafa09a", + "bytecodeHash": "0x01000047096f5dab39055215639242142c662792eda46d46f8a4a5994098e9d3", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013ffa100e6cdf59d3f25ae78d832cd1feffbf0ebe22af08d90986097a5d", + "bytecodeHash": "0x0100013fc103b8e9c8823f0b5f607b54c3ced652b073481d7944b801d45b6136", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x0100062f3a64baacbc8bfa773c162913940f5e4efe70f87b2bb919c52e92b3d2", - "sourceCodeHash": "0xd26f48108304f2dcde3c85bb6add5095e9241f70b4fef03bff4b37bdad159fed" + "bytecodeHash": "0x010006899163a15f72c2af3cc5501a19f422506d2c08967f184c084d7a8a4b61", + "sourceCodeHash": "0xa89aa977537c1883e5f99eb22b22b1326a1cca179c7201a26a6678846d6145b6" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003f7dffcaa5e1013247a5da647824751cea975531af39b5aa8a1ceb04b6", + "bytecodeHash": "0x0100003f22e7d580bc8e7543d921ac35aa24019162107a8c770a76e23df573a5", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100050368138aaf52ed6bce4e180805eb72b4aaab97fd6fffa038cb457b62f1", - "sourceCodeHash": "0xb41382ac3d04739da79e438ee977b535bfb1c10b0dd4766f88b954b10d2710be" + "bytecodeHash": "0x01000509c4ed190e1d976223ef1d9d5e1441450b8c90c81ba9db7ac3143bd655", + "sourceCodeHash": "0x62e525189d13e7d59a88cfe834621bc7fb62cd38e2d830f9a1d1e056e229d2c8" }, { "contractName": "EmptyContract", @@ -59,56 +59,56 @@ "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033c30d3d524b93a943e8dd7dba3d096730c12d5b3bb52311c55f812eed", + "bytecodeHash": "0x01000033bda7d60ad38b3df947d9143234528aa9c828212a60192d671341b993", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000c1d21b617f9bfe5e54df06ecefbb4777e0da3d8c6c23bbc10fb8234ed2", + "bytecodeHash": "0x010000c11f196173983c4e73b40f008b8ff0f44ccee9af74ca53568b925abe4c", "sourceCodeHash": "0xeb83e3a2ea2f50b93122363b8dd56fbcfe821d11723d849eecbde3d6af1147de" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x0100026581914e835a621a69f53930a4c01380a7215ec525c2a0fdd421d0a226", + "bytecodeHash": "0x01000265037281ade86b965c995ebfee9b395e4bc8de5a4271fbf145d6186509", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f3236c6465720a9ed7e62139ab585fbc03736c6a2fde4775911c9ba9eb", + "bytecodeHash": "0x010000f335bd082f4c62cbb2892f1d4942165dec7ef43bdf017e5f48a539a637", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005947b1d73fa00f1f900b1763c769cb5509d11912153fdc4c952b8bc218", + "bytecodeHash": "0x01000059f9bba78e1a9975df14c25faf992f0a68056a1d16976ba5e8cd36e3f5", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cf060faf52ba4c9517d70710995e65e14ab74a246e2f5a58a0dbebeafc", + "bytecodeHash": "0x010000cfd7cf22490b8b82005cec551cba1a3de65ed34089ecfa338a795afd44", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041fcc8bf42926b7204852d1e6ead584091a7dad67f0f6ffaf65e674d2a", + "bytecodeHash": "0x0100004122b8a5696b8516afc2b2402428c27a088b7cba4a9e089637ad75cddc", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c569017612e96a242865c78116d801c320f13a9bdfa0ad7efb206dce3a", + "bytecodeHash": "0x010001c5ca32776369b696e34a5894d3b272c4f2a4f1ae04d0cb43d5da90adea", "sourceCodeHash": "0xc5ce25a94e3b510183635dd2fe0152dbcaa705bc8802fb3a4390253b5af3aa0a" }, { @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cd9299d4a01997c340dc652d8467be23821446ce01fc89f9cb92f6b17ae", - "sourceCodeHash": "0x72a51372b295914998e75d36df5f4f8d834e1eab797765839823e39b1e32c64d" + "bytecodeHash": "0x01000cd957604ca7e653a0fa0e80e96bd575b52e6d07182fad2fecb3fa6cd7d1", + "sourceCodeHash": "0x1ad51b4b8b559793df21ff15e03aea492563040763ace8f231b8be12ff7c6767" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 15c74806a..2e1278d33 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -176,38 +176,71 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { return createAccount(_salt, _bytecodeHash, _input, AccountAbstractionVersion.None); } - function createEVM(bytes calldata _initCode) external payable override returns (address) { - // TODO only for semantic tests? - uint256 deploymentNonce = NONCE_HOLDER_SYSTEM_CONTRACT.getDeploymentNonce(msg.sender); - if ((msg.sender != tx.origin) && deploymentNonce == 0) { - NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); + function createEVM(bytes calldata _initCode) external payable override onlySystemCall returns (address) { + uint256 senderNonce; + // If the account is an EOA, use the min nonce. If it's a contract, use deployment nonce + if (msg.sender == tx.origin) { + // Subtract 1 for EOA since the nonce has already been incremented for this transaction + senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.getMinNonce(msg.sender) - 1; + } else { + // Deploy from EraVM context + senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.getDeploymentNonce(msg.sender); + // TODO only for semantic tests? + if (senderNonce == 0) { + NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); + } + + senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); } - // 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); address newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); - // If the method is called by an EVM contract, then we need to increase deployment - // nonce for a contract even if contract creation actually failed - if (SystemContractHelper.isSystemCall() && ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender)) { - // EVM emulator provides infinite gas - try this.evmDeployOnAddress{value: msg.value}(msg.sender, newAddress, _initCode) {} catch { - newAddress = address(0); - } - } else { - this.evmDeployOnAddress{value: msg.value}(msg.sender, newAddress, _initCode); + _evmDeployOnAddress(msg.sender, newAddress, _initCode); + + return newAddress; + } + + function prepareForEvmCreateFromEmulator() public onlySystemCallFromEvmEmulator returns (address) { + if (_getAllowedBytecodeTypesMode() != AllowedBytecodeTypes.EraVmAndEVM) { + revert EVMEmulationNotSupported(); } - //_evmDeployOnAddress(newAddress, _initCode); + return address(0); // TODO solidity semantic tests are invalid, remove it later + + // TODO uncomment + /* + uint256 senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); + + address newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); + + // 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); return newAddress; + */ } - function evmDeployOnAddress(address _sender, address _newAddress, bytes calldata _initCode) external payable onlySelf { - _evmDeployOnAddress(_sender, _newAddress, _initCode); + /// Note: only possible revert case should be due to revert in the called constructor + function createEvmFromEmulator( + address newAddress, + bytes calldata _initCode + ) external payable onlySystemCallFromEvmEmulator returns (address) { + // ##### TODO solidity semantic tests are invalid, remove it later + { + uint256 senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); + + newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); + + // 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); + } + // ##### END TODO + + _evmDeployOnAddress(msg.sender, newAddress, _initCode); + + return newAddress; } /// @notice Deploys an EVM contract using address derivation of EVM's `CREATE2` opcode @@ -215,7 +248,10 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { /// @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) { + function create2EVM( + bytes32 _salt, + bytes calldata _initCode + ) external payable override onlySystemCall returns (address) { // No collision is possible with the zksync's non-EVM CREATE2, since // the prefixes are different bytes32 bytecodeHash = EfficientCall.keccak(_initCode); diff --git a/system-contracts/contracts/DefaultAccount.sol b/system-contracts/contracts/DefaultAccount.sol index 78197856f..aa6ce50a5 100644 --- a/system-contracts/contracts/DefaultAccount.sol +++ b/system-contracts/contracts/DefaultAccount.sol @@ -141,7 +141,13 @@ contract DefaultAccount is IAccount { // TODO: if possible, maybe implement some way to avoid memory copying here. if ((_transaction.reserved[1] != 0) && (to == address(0))) { - DEPLOYER_SYSTEM_CONTRACT.createEVM{value: value}(data); + // Note, that createEVM can only be called with "isSystem" flag. + SystemContractsCaller.systemCallWithPropagatedRevert( + uint32(gasleft()), + address(DEPLOYER_SYSTEM_CONTRACT), + value, + abi.encodeCall(DEPLOYER_SYSTEM_CONTRACT.createEVM, (data)) + ); return; } diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index bc70d33af..c76c01b9e 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -76,6 +76,10 @@ object "EvmEmulator" { addr := 0x0000000000000000000000000000000000008013 } + function MSG_VALUE_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008009 + } + function LAST_RETURNDATA_SIZE_OFFSET() -> offset { offset := mul(32, 32) } @@ -1012,6 +1016,40 @@ object "EvmEmulator" { // CREATE FUNCTIONALITY //////////////////////////////////////////////////////////////// + function performSystemCallForCreate( + value, + bytecodeStart, + bytecodeLen, + ) -> success { + let farCallAbi := shl(248, 1) // system call + // dataOffset is 0 + farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) + farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) + farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + // shardId is 0 + // forwardingMode is 0 + // not constructor call (ContractDeployer will call constructor) + + switch iszero(value) + case 0 { + success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, DEPLOYER_SYSTEM_CONTRACT(), 1, 0) + } + default { + success := verbatim_6i_1o("system_call", DEPLOYER_SYSTEM_CONTRACT(), farCallAbi, 0, 0, 0, 0) + } + } + + function incrementDeploymentNonce() -> nonce { + // function incrementDeploymentNonce(address _address) + mstore(0, 0x306395c600000000000000000000000000000000000000000000000000000000) + mstore(4, address()) + + performSystemCall(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) + + returndatacopy(0, 0, 32) + nonce := mload(0) + } + function _fetchConstructorReturnGas() -> gasLeft { mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) @@ -1042,7 +1080,7 @@ object "EvmEmulator" { _pushEVMFrame(gasForTheCall, false) if isCreate2 { - // Create2EVM selector + // selector: create2EVM(bytes32 _salt, bytes calldata _initCode) mstore(sub(offset, 0x80), 0x4e96f4c0) // salt mstore(sub(offset, 0x60), salt) @@ -1051,31 +1089,47 @@ object "EvmEmulator" { // 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) + result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) } if iszero(isCreate2) { - // CreateEVM selector - mstore(sub(offset, 0x60), 0xff311601) - // Where the arg starts (second word) - mstore(sub(offset, 0x40), 0x20) + if gt(value, selfbalance()) { // it should be checked before actual deploy call + panic() + } + + // we want to calculate the address of new contract + // and if it is deployable, we need to increment deploy nonce + + // selector: function prepareForEvmCreateFromEmulator() + mstore(0, 0x3ec89a4e00000000000000000000000000000000000000000000000000000000) + performSystemCall(DEPLOYER_SYSTEM_CONTRACT(), 4) + returndatacopy(0, 0, 32) + addr := mload(0) + + // so even if constructor reverts, nonce stays incremented + + // selector: function createEvmFromEmulator(address newAddress, bytes calldata _initCode) + mstore(sub(offset, 0x80), 0xe43cec64) + // address + mstore(sub(offset, 0x60), addr) + // 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, 0x44), add(size, 0x44), 0, 32) + result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) } - addr := mload(0) - let gasLeft switch result case 0 { + addr := 0 gasLeft := _saveReturndataAfterEVMCall(0, 0) } default { + returndatacopy(0, 0, 32) + addr := mload(0) gasLeft := _fetchConstructorReturnGas() } @@ -3032,6 +3086,10 @@ object "EvmEmulator" { addr := 0x0000000000000000000000000000000000008013 } + function MSG_VALUE_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008009 + } + function LAST_RETURNDATA_SIZE_OFFSET() -> offset { offset := mul(32, 32) } @@ -3968,6 +4026,40 @@ object "EvmEmulator" { // CREATE FUNCTIONALITY //////////////////////////////////////////////////////////////// + function performSystemCallForCreate( + value, + bytecodeStart, + bytecodeLen, + ) -> success { + let farCallAbi := shl(248, 1) // system call + // dataOffset is 0 + farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) + farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) + farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + // shardId is 0 + // forwardingMode is 0 + // not constructor call (ContractDeployer will call constructor) + + switch iszero(value) + case 0 { + success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, DEPLOYER_SYSTEM_CONTRACT(), 1, 0) + } + default { + success := verbatim_6i_1o("system_call", DEPLOYER_SYSTEM_CONTRACT(), farCallAbi, 0, 0, 0, 0) + } + } + + function incrementDeploymentNonce() -> nonce { + // function incrementDeploymentNonce(address _address) + mstore(0, 0x306395c600000000000000000000000000000000000000000000000000000000) + mstore(4, address()) + + performSystemCall(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) + + returndatacopy(0, 0, 32) + nonce := mload(0) + } + function _fetchConstructorReturnGas() -> gasLeft { mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) @@ -3998,7 +4090,7 @@ object "EvmEmulator" { _pushEVMFrame(gasForTheCall, false) if isCreate2 { - // Create2EVM selector + // selector: create2EVM(bytes32 _salt, bytes calldata _initCode) mstore(sub(offset, 0x80), 0x4e96f4c0) // salt mstore(sub(offset, 0x60), salt) @@ -4007,31 +4099,47 @@ object "EvmEmulator" { // 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) + result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) } if iszero(isCreate2) { - // CreateEVM selector - mstore(sub(offset, 0x60), 0xff311601) - // Where the arg starts (second word) - mstore(sub(offset, 0x40), 0x20) + if gt(value, selfbalance()) { // it should be checked before actual deploy call + panic() + } + + // we want to calculate the address of new contract + // and if it is deployable, we need to increment deploy nonce + + // selector: function prepareForEvmCreateFromEmulator() + mstore(0, 0x3ec89a4e00000000000000000000000000000000000000000000000000000000) + performSystemCall(DEPLOYER_SYSTEM_CONTRACT(), 4) + returndatacopy(0, 0, 32) + addr := mload(0) + + // so even if constructor reverts, nonce stays incremented + + // selector: function createEvmFromEmulator(address newAddress, bytes calldata _initCode) + mstore(sub(offset, 0x80), 0xe43cec64) + // address + mstore(sub(offset, 0x60), addr) + // 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, 0x44), add(size, 0x44), 0, 32) + result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) } - addr := mload(0) - let gasLeft switch result case 0 { + addr := 0 gasLeft := _saveReturndataAfterEVMCall(0, 0) } default { + returndatacopy(0, 0, 32) + addr := mload(0) gasLeft := _fetchConstructorReturnGas() } diff --git a/system-contracts/contracts/abstract/SystemContractBase.sol b/system-contracts/contracts/abstract/SystemContractBase.sol index bcbc8b64e..613f7d49c 100644 --- a/system-contracts/contracts/abstract/SystemContractBase.sol +++ b/system-contracts/contracts/abstract/SystemContractBase.sol @@ -60,4 +60,13 @@ abstract contract SystemContractBase { } _; } + + /// @notice Modifier that makes sure that the method + /// can only be called from the EVM emulator using system call (unaccessible from EVM environment) + modifier onlySystemCallFromEvmEmulator() { + if (!SystemContractHelper.isSystemCallFromEvmEmulator()) { + revert CallerMustBeEvmContract(); + } + _; + } } diff --git a/system-contracts/contracts/libraries/SystemContractHelper.sol b/system-contracts/contracts/libraries/SystemContractHelper.sol index b5934e96a..6b3690149 100644 --- a/system-contracts/contracts/libraries/SystemContractHelper.sol +++ b/system-contracts/contracts/libraries/SystemContractHelper.sol @@ -2,7 +2,7 @@ // 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; -import {MAX_SYSTEM_CONTRACT_ADDRESS} from "../Constants.sol"; +import {MAX_SYSTEM_CONTRACT_ADDRESS, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} 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} from "./SystemContractsCaller.sol"; @@ -346,6 +346,13 @@ library SystemContractHelper { return uint160(_address) <= uint160(MAX_SYSTEM_CONTRACT_ADDRESS); } + /// @notice Returns whether the current call is a system call from EVM emulator. + /// @return `true` or `false` based on whether the current call is a system call from EVM emulator. + function isSystemCallFromEvmEmulator() internal view returns (bool) { + if (!isSystemCall()) return false; + return ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.isAccountEVM(msg.sender); + } + /// @notice Method used for burning a certain amount of gas. /// @param _gasToPay The number of gas to burn. /// @param _pubdataToSpend The number of pubdata bytes to burn during the call. diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index c3288c33e..65839af46 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -22,6 +22,10 @@ function EVM_GAS_MANAGER_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008013 } +function MSG_VALUE_SYSTEM_CONTRACT() -> addr { + addr := 0x0000000000000000000000000000000000008009 +} + function LAST_RETURNDATA_SIZE_OFFSET() -> offset { offset := mul(32, 32) } @@ -958,6 +962,40 @@ function _eraseReturndataPointer() { // CREATE FUNCTIONALITY //////////////////////////////////////////////////////////////// +function performSystemCallForCreate( + value, + bytecodeStart, + bytecodeLen, +) -> success { + let farCallAbi := shl(248, 1) // system call + // dataOffset is 0 + farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) + farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) + farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + // shardId is 0 + // forwardingMode is 0 + // not constructor call (ContractDeployer will call constructor) + + switch iszero(value) + case 0 { + success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, DEPLOYER_SYSTEM_CONTRACT(), 1, 0) + } + default { + success := verbatim_6i_1o("system_call", DEPLOYER_SYSTEM_CONTRACT(), farCallAbi, 0, 0, 0, 0) + } +} + +function incrementDeploymentNonce() -> nonce { + // function incrementDeploymentNonce(address _address) + mstore(0, 0x306395c600000000000000000000000000000000000000000000000000000000) + mstore(4, address()) + + performSystemCall(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) + + returndatacopy(0, 0, 32) + nonce := mload(0) +} + function _fetchConstructorReturnGas() -> gasLeft { mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) @@ -988,7 +1026,7 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO _pushEVMFrame(gasForTheCall, false) if isCreate2 { - // Create2EVM selector + // selector: create2EVM(bytes32 _salt, bytes calldata _initCode) mstore(sub(offset, 0x80), 0x4e96f4c0) // salt mstore(sub(offset, 0x60), salt) @@ -997,31 +1035,47 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftO // 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) + result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) } if iszero(isCreate2) { - // CreateEVM selector - mstore(sub(offset, 0x60), 0xff311601) - // Where the arg starts (second word) - mstore(sub(offset, 0x40), 0x20) + if gt(value, selfbalance()) { // it should be checked before actual deploy call + panic() + } + + // we want to calculate the address of new contract + // and if it is deployable, we need to increment deploy nonce + + // selector: function prepareForEvmCreateFromEmulator() + mstore(0, 0x3ec89a4e00000000000000000000000000000000000000000000000000000000) + performSystemCall(DEPLOYER_SYSTEM_CONTRACT(), 4) + returndatacopy(0, 0, 32) + addr := mload(0) + + // so even if constructor reverts, nonce stays incremented + + // selector: function createEvmFromEmulator(address newAddress, bytes calldata _initCode) + mstore(sub(offset, 0x80), 0xe43cec64) + // address + mstore(sub(offset, 0x60), addr) + // 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, 0x44), add(size, 0x44), 0, 32) + result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) } - addr := mload(0) - let gasLeft switch result case 0 { + addr := 0 gasLeft := _saveReturndataAfterEVMCall(0, 0) } default { + returndatacopy(0, 0, 32) + addr := mload(0) gasLeft := _fetchConstructorReturnGas() } From 2fb5df419299180e0ed38c282b7f46322fa07bec Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 25 Oct 2024 17:34:27 +0200 Subject: [PATCH 099/183] Fix(EVM): Fix keccak gas charge flow (#996) --- system-contracts/SystemContractsHashes.json | 8 ++++---- system-contracts/contracts/EvmEmulator.yul | 10 ++++------ .../evm-emulator/EvmEmulatorLoop.template.yul | 5 ++--- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 5996afe39..35a0c1b1c 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": "0x010006899163a15f72c2af3cc5501a19f422506d2c08967f184c084d7a8a4b61", - "sourceCodeHash": "0xa89aa977537c1883e5f99eb22b22b1326a1cca179c7201a26a6678846d6145b6" + "bytecodeHash": "0x010006893b07703146f0b1c9b4cd9d481e206eef99147d13fea699be2fdc8ad9", + "sourceCodeHash": "0xa4c2c1f55f5ef1281e18fd016865d9b83b71ad7facb2fd5130940b3b0b7de621" }, { "contractName": "Create2Factory", @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cd957604ca7e653a0fa0e80e96bd575b52e6d07182fad2fecb3fa6cd7d1", - "sourceCodeHash": "0x1ad51b4b8b559793df21ff15e03aea492563040763ace8f231b8be12ff7c6767" + "bytecodeHash": "0x01000cd17989fbfbda00c1058d3cbe559dcd05ff07a71e9182f198e22d622cc0", + "sourceCodeHash": "0x43c82a32662ed95d5ecb809535f8487a04c14cbeedcd67eeb29bb33bf5bc74fd" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index c76c01b9e..ad8595955 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1559,8 +1559,6 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) - 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 @@ -1568,7 +1566,8 @@ object "EvmEmulator" { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - stackHead := keccak + stackHead := keccak256(add(MEM_OFFSET_INNER(), offset), size) + ip := add(ip, 1) } case 0x30 { // OP_ADDRESS @@ -4569,8 +4568,6 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) - 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 @@ -4578,7 +4575,8 @@ object "EvmEmulator" { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - stackHead := keccak + stackHead := keccak256(add(MEM_OFFSET_INNER(), offset), size) + ip := add(ip, 1) } case 0x30 { // OP_ADDRESS diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 907fce9ea..cd8af797b 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -284,8 +284,6 @@ for { } true { } { checkMemIsAccessible(offset, size) - 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 @@ -293,7 +291,8 @@ for { } true { } { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(add(offset, size))) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - stackHead := keccak + stackHead := keccak256(add(MEM_OFFSET_INNER(), offset), size) + ip := add(ip, 1) } case 0x30 { // OP_ADDRESS From 9555afc5e808c621c8934f7cf0ea4e7ce6b25983 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 25 Oct 2024 18:08:19 +0200 Subject: [PATCH 100/183] fix(EVM): Fix precompiles gas flow (#998) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 112 ++++++++++++------ .../EvmEmulatorFunctions.template.yul | 56 ++++++--- 3 files changed, 113 insertions(+), 59 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 35a0c1b1c..2c7cc6eb1 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cd17989fbfbda00c1058d3cbe559dcd05ff07a71e9182f198e22d622cc0", - "sourceCodeHash": "0x43c82a32662ed95d5ecb809535f8487a04c14cbeedcd67eeb29bb33bf5bc74fd" + "bytecodeHash": "0x01000cfb8eb0e02f35ed77623c89d2d3c34783721996aa70190c90b187ed851e", + "sourceCodeHash": "0x2bb96c3957fdee6343c64d00921914c4b01aaad70d6c3ff2bd263c1fbd67110a" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index ad8595955..0074f1a9c 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -631,6 +631,14 @@ object "EvmEmulator" { gasToPass := capGasForCall(evmGasLeft, gasToPass) + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + if precompileCost { + if lt(gasToPass, precompileCost) { + evmGasLeft := chargeGas(evmGasLeft, gasToPass) + gasToPass := 0 + } + } + let success, frameGasLeft := _performCall( addr, gasToPass, @@ -641,19 +649,20 @@ object "EvmEmulator" { retSize ) - let gasUsed := 0 + let gasUsedByCall := sub(gasToPass, frameGasLeft) - // TODO precompile should be called, but return nothing if gasPassed is too low - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - switch iszero(precompileCost) - case 1 { - gasUsed := sub(gasToPass, frameGasLeft) - } - default { - gasUsed := precompileCost + if precompileCost { + switch success + case 0 { + gasUsedByCall := gasToPass + } + default { + gasUsedByCall := precompileCost + } } - newGasLeft := chargeGas(evmGasLeft, gasUsed) + newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) + stackHead := success } @@ -686,6 +695,14 @@ object "EvmEmulator" { gasToPass := capGasForCall(evmGasLeft, gasToPass) + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + if precompileCost { + if lt(gasToPass, precompileCost) { + evmGasLeft := chargeGas(evmGasLeft, gasToPass) + gasToPass := 0 + } + } + let success, frameGasLeft := _performStaticCall( addr, gasToPass, @@ -695,18 +712,19 @@ object "EvmEmulator" { retSize ) - let gasUsed := 0 + let gasUsedByCall := sub(gasToPass, frameGasLeft) - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - switch iszero(precompileCost) - case 1 { - gasUsed := sub(gasToPass, frameGasLeft) - } - default { - gasUsed := precompileCost + if precompileCost { + switch success + case 0 { + gasUsedByCall := gasToPass + } + default { + gasUsedByCall := precompileCost + } } - newGasLeft := chargeGas(evmGasLeft, gasUsed) + newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) stackHead := success } @@ -3640,6 +3658,14 @@ object "EvmEmulator" { gasToPass := capGasForCall(evmGasLeft, gasToPass) + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + if precompileCost { + if lt(gasToPass, precompileCost) { + evmGasLeft := chargeGas(evmGasLeft, gasToPass) + gasToPass := 0 + } + } + let success, frameGasLeft := _performCall( addr, gasToPass, @@ -3650,19 +3676,20 @@ object "EvmEmulator" { retSize ) - let gasUsed := 0 + let gasUsedByCall := sub(gasToPass, frameGasLeft) - // TODO precompile should be called, but return nothing if gasPassed is too low - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - switch iszero(precompileCost) - case 1 { - gasUsed := sub(gasToPass, frameGasLeft) - } - default { - gasUsed := precompileCost + if precompileCost { + switch success + case 0 { + gasUsedByCall := gasToPass + } + default { + gasUsedByCall := precompileCost + } } - newGasLeft := chargeGas(evmGasLeft, gasUsed) + newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) + stackHead := success } @@ -3695,6 +3722,14 @@ object "EvmEmulator" { gasToPass := capGasForCall(evmGasLeft, gasToPass) + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + if precompileCost { + if lt(gasToPass, precompileCost) { + evmGasLeft := chargeGas(evmGasLeft, gasToPass) + gasToPass := 0 + } + } + let success, frameGasLeft := _performStaticCall( addr, gasToPass, @@ -3704,18 +3739,19 @@ object "EvmEmulator" { retSize ) - let gasUsed := 0 + let gasUsedByCall := sub(gasToPass, frameGasLeft) - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - switch iszero(precompileCost) - case 1 { - gasUsed := sub(gasToPass, frameGasLeft) - } - default { - gasUsed := precompileCost + if precompileCost { + switch success + case 0 { + gasUsedByCall := gasToPass + } + default { + gasUsedByCall := precompileCost + } } - newGasLeft := chargeGas(evmGasLeft, gasUsed) + newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) stackHead := success } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 65839af46..7c0d35b61 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -577,6 +577,14 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe gasToPass := capGasForCall(evmGasLeft, gasToPass) + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + if precompileCost { + if lt(gasToPass, precompileCost) { + evmGasLeft := chargeGas(evmGasLeft, gasToPass) + gasToPass := 0 + } + } + let success, frameGasLeft := _performCall( addr, gasToPass, @@ -587,19 +595,20 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe retSize ) - let gasUsed := 0 + let gasUsedByCall := sub(gasToPass, frameGasLeft) - // TODO precompile should be called, but return nothing if gasPassed is too low - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - switch iszero(precompileCost) - case 1 { - gasUsed := sub(gasToPass, frameGasLeft) - } - default { - gasUsed := precompileCost + if precompileCost { + switch success + case 0 { + gasUsedByCall := gasToPass + } + default { + gasUsedByCall := precompileCost + } } - newGasLeft := chargeGas(evmGasLeft, gasUsed) + newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) + stackHead := success } @@ -632,6 +641,14 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s gasToPass := capGasForCall(evmGasLeft, gasToPass) + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + if precompileCost { + if lt(gasToPass, precompileCost) { + evmGasLeft := chargeGas(evmGasLeft, gasToPass) + gasToPass := 0 + } + } + let success, frameGasLeft := _performStaticCall( addr, gasToPass, @@ -641,18 +658,19 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s retSize ) - let gasUsed := 0 + let gasUsedByCall := sub(gasToPass, frameGasLeft) - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - switch iszero(precompileCost) - case 1 { - gasUsed := sub(gasToPass, frameGasLeft) - } - default { - gasUsed := precompileCost + if precompileCost { + switch success + case 0 { + gasUsedByCall := gasToPass + } + default { + gasUsedByCall := precompileCost + } } - newGasLeft := chargeGas(evmGasLeft, gasUsed) + newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) stackHead := success } From 781f9fd5918177723d4a844c7c5448fcc3f78f33 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 25 Oct 2024 23:08:47 +0200 Subject: [PATCH 101/183] fix(EVM): Fix ecPairing dynamic gas cost (#1003) --- system-contracts/SystemContractsHashes.json | 4 ++-- system-contracts/contracts/EvmEmulator.yul | 8 ++++---- .../evm-emulator/EvmEmulatorFunctions.template.yul | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 2c7cc6eb1..7101306c9 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cfb8eb0e02f35ed77623c89d2d3c34783721996aa70190c90b187ed851e", - "sourceCodeHash": "0x2bb96c3957fdee6343c64d00921914c4b01aaad70d6c3ff2bd263c1fbd67110a" + "bytecodeHash": "0x01000cfb484a41fd30cb980370aa9299c9ef3de282a6680afedf20ac44df67e4", + "sourceCodeHash": "0x8def10a125453a100264d1d5e5164466f0fac1438af8cf9a26394f97b20d93ae" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 0074f1a9c..ea0c09d9b 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -969,12 +969,12 @@ object "EvmEmulator" { // 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. + // 34,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)) + gasToCharge := add(gasToCharge, mul(k, 34000)) } case 0x09 { // blake2f // argsOffset[0; 3] (4 bytes) Number of rounds (big-endian uint) @@ -3996,12 +3996,12 @@ object "EvmEmulator" { // 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. + // 34,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)) + gasToCharge := add(gasToCharge, mul(k, 34000)) } case 0x09 { // blake2f // argsOffset[0; 3] (4 bytes) Number of rounds (big-endian uint) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 7c0d35b61..e62a75242 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -915,12 +915,12 @@ function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { // 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. + // 34,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)) + gasToCharge := add(gasToCharge, mul(k, 34000)) } case 0x09 { // blake2f // argsOffset[0; 3] (4 bytes) Number of rounds (big-endian uint) From 988d476205706df496423ab0cfaabfbf54865f99 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sat, 26 Oct 2024 00:36:19 +0200 Subject: [PATCH 102/183] fix(EVM): Fix gas stipends (#1005) --- system-contracts/SystemContractsHashes.json | 4 +-- system-contracts/contracts/EvmEmulator.yul | 34 ++++++++++++++----- .../EvmEmulatorFunctions.template.yul | 17 +++++++--- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 7101306c9..49de19eda 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cfb484a41fd30cb980370aa9299c9ef3de282a6680afedf20ac44df67e4", - "sourceCodeHash": "0x8def10a125453a100264d1d5e5164466f0fac1438af8cf9a26394f97b20d93ae" + "bytecodeHash": "0x01000cf9d59b9e34c6649c736198c465f24007e0da13ab3e56a52af0a20ae818", + "sourceCodeHash": "0xfe1baab0cc69a9c81dc255095147e34ceed4025a263f07f119ae6a2424d495fe" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index ea0c09d9b..20b09450e 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -122,7 +122,14 @@ object "EvmEmulator" { // 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 + + // We need to pass some gas for MsgValueSimulator internal logic + function MSG_VALUE_SIMULATOR_STIPEND_GAS() -> gas_stipend { + gas_stipend := 30000 // 27000 + a little bit more + } + function OVERHEAD() -> overhead { overhead := 2000 } // From precompiles/CodeOracle @@ -765,8 +772,7 @@ object "EvmEmulator" { _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( - // We can not just pass all gas here to prevent overflow of zkEVM gas counter - EVM_GAS_STIPEND(), + 0, // 0 gas since VM will add EVM_GAS_STIPEND() to gas addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, @@ -798,7 +804,10 @@ object "EvmEmulator" { } default { _pushEVMFrame(gasToPass, false) - success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + // VM will add EVM_GAS_STIPEND() to gas for this call + // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract + // so we need to pass some gas for MsgValueSimulator + success := call(MSG_VALUE_SIMULATOR_STIPEND_GAS(), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } @@ -819,7 +828,7 @@ object "EvmEmulator" { } default { _pushEVMFrame(gasToPass, true) - success := staticcall(EVM_GAS_STIPEND(), addr, argsOffset, argsSize, 0, 0) + success := staticcall(0, addr, argsOffset, argsSize, 0, 0) // 0 gas since VM will add EVM_GAS_STIPEND() to gas frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } @@ -3149,7 +3158,14 @@ object "EvmEmulator" { // 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 + + // We need to pass some gas for MsgValueSimulator internal logic + function MSG_VALUE_SIMULATOR_STIPEND_GAS() -> gas_stipend { + gas_stipend := 30000 // 27000 + a little bit more + } + function OVERHEAD() -> overhead { overhead := 2000 } // From precompiles/CodeOracle @@ -3792,8 +3808,7 @@ object "EvmEmulator" { _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( - // We can not just pass all gas here to prevent overflow of zkEVM gas counter - EVM_GAS_STIPEND(), + 0, // 0 gas since VM will add EVM_GAS_STIPEND() to gas addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, @@ -3825,7 +3840,10 @@ object "EvmEmulator" { } default { _pushEVMFrame(gasToPass, false) - success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + // VM will add EVM_GAS_STIPEND() to gas for this call + // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract + // so we need to pass some gas for MsgValueSimulator + success := call(MSG_VALUE_SIMULATOR_STIPEND_GAS(), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } @@ -3846,7 +3864,7 @@ object "EvmEmulator" { } default { _pushEVMFrame(gasToPass, true) - success := staticcall(EVM_GAS_STIPEND(), addr, argsOffset, argsSize, 0, 0) + success := staticcall(0, addr, argsOffset, argsSize, 0, 0) // 0 gas since VM will add EVM_GAS_STIPEND() to gas frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index e62a75242..de18a50f4 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -68,7 +68,14 @@ function INF_PASS_GAS() -> inf { // 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 + +// We need to pass some gas for MsgValueSimulator internal logic +function MSG_VALUE_SIMULATOR_STIPEND_GAS() -> gas_stipend { + gas_stipend := 30000 // 27000 + a little bit more +} + function OVERHEAD() -> overhead { overhead := 2000 } // From precompiles/CodeOracle @@ -711,8 +718,7 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEv _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( - // We can not just pass all gas here to prevent overflow of zkEVM gas counter - EVM_GAS_STIPEND(), + 0, // 0 gas since VM will add EVM_GAS_STIPEND() to gas addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, @@ -744,7 +750,10 @@ function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, r } default { _pushEVMFrame(gasToPass, false) - success := call(EVM_GAS_STIPEND(), addr, value, argsOffset, argsSize, 0, 0) + // VM will add EVM_GAS_STIPEND() to gas for this call + // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract + // so we need to pass some gas for MsgValueSimulator + success := call(MSG_VALUE_SIMULATOR_STIPEND_GAS(), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } @@ -765,7 +774,7 @@ function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, re } default { _pushEVMFrame(gasToPass, true) - success := staticcall(EVM_GAS_STIPEND(), addr, argsOffset, argsSize, 0, 0) + success := staticcall(0, addr, argsOffset, argsSize, 0, 0) // 0 gas since VM will add EVM_GAS_STIPEND() to gas frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } From 17698ed74cd2b1b3780333e6f1b40af6f5d106ea Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sat, 26 Oct 2024 01:09:49 +0200 Subject: [PATCH 103/183] fix(EVM): Fix MCOPY gas cost (#1006) --- system-contracts/SystemContractsHashes.json | 4 ++-- system-contracts/contracts/EvmEmulator.yul | 20 +++++++++++-------- .../evm-emulator/EvmEmulatorLoop.template.yul | 10 ++++++---- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 49de19eda..c1995800e 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cf9d59b9e34c6649c736198c465f24007e0da13ab3e56a52af0a20ae818", - "sourceCodeHash": "0xfe1baab0cc69a9c81dc255095147e34ceed4025a263f07f119ae6a2424d495fe" + "bytecodeHash": "0x01000cfbea1cd2554885558bf83c1b47b12f18a264656297ac0e772293e399d8", + "sourceCodeHash": "0x4136a3f1ad59c5ec4c93a1b2a5a8508b3b7e36e30b66d8a7805149f3274bbb5d" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 20b09450e..5e31656c0 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -2076,10 +2076,12 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) checkMemIsAccessible(destOffset, size) - { - let maxExpand := getMaxMemoryExpansionCost(offset, size, destOffset, size) - evmGasLeft := chargeGas(evmGasLeft, maxExpand) - } + // dynamic_gas = 3 * words_copied + memory_expansion_cost + let dynamicGas := getMaxMemoryExpansionCost(offset, size, destOffset, size) + let wordsCopied := div(add(size, 31), 32) // div rounding up + dynamicGas := add(dynamicGas, mul(3, wordsCopied)) + + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) ip := add(ip, 1) @@ -5112,10 +5114,12 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) checkMemIsAccessible(destOffset, size) - { - let maxExpand := getMaxMemoryExpansionCost(offset, size, destOffset, size) - evmGasLeft := chargeGas(evmGasLeft, maxExpand) - } + // dynamic_gas = 3 * words_copied + memory_expansion_cost + let dynamicGas := getMaxMemoryExpansionCost(offset, size, destOffset, size) + let wordsCopied := div(add(size, 31), 32) // div rounding up + dynamicGas := add(dynamicGas, mul(3, wordsCopied)) + + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) ip := add(ip, 1) diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index cd8af797b..5277f290c 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -774,10 +774,12 @@ for { } true { } { checkMemIsAccessible(offset, size) checkMemIsAccessible(destOffset, size) - { - let maxExpand := getMaxMemoryExpansionCost(offset, size, destOffset, size) - evmGasLeft := chargeGas(evmGasLeft, maxExpand) - } + // dynamic_gas = 3 * words_copied + memory_expansion_cost + let dynamicGas := getMaxMemoryExpansionCost(offset, size, destOffset, size) + let wordsCopied := div(add(size, 31), 32) // div rounding up + dynamicGas := add(dynamicGas, mul(3, wordsCopied)) + + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) ip := add(ip, 1) From e9819ec7fbcabb65e52d9268e2b1440195edddb8 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sat, 26 Oct 2024 01:33:06 +0200 Subject: [PATCH 104/183] fix(EVM): Fix EXP gas cost flow (#1007) --- system-contracts/SystemContractsHashes.json | 4 ++-- system-contracts/contracts/EvmEmulator.yul | 20 +++++++++++-------- .../evm-emulator/EvmEmulatorLoop.template.yul | 10 ++++++---- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index c1995800e..6d2a9c8ee 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cfbea1cd2554885558bf83c1b47b12f18a264656297ac0e772293e399d8", - "sourceCodeHash": "0x4136a3f1ad59c5ec4c93a1b2a5a8508b3b7e36e30b66d8a7805149f3274bbb5d" + "bytecodeHash": "0x01000cf74eb8015735f39ee5568f6025c9e789d2d73c9b5510614e6296c87341", + "sourceCodeHash": "0xf5d31991d176ac5beca9190ae39fae9e17f32bfe78d4359d6c564959b5478868" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 5e31656c0..c7c07049d 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1418,14 +1418,16 @@ object "EvmEmulator" { popStackCheck(sp, 2) a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) - stackHead := exp(a, exponent) - let to_charge := 0 - for {} gt(exponent,0) {} { // while exponent > 0 + let exponentCopy := exponent + for {} gt(exponentCopy, 0) {} { // while exponent > 0 to_charge := add(to_charge, 50) - exponent := shr(8, exponent) + exponentCopy := shr(8, exponentCopy) } evmGasLeft := chargeGas(evmGasLeft, to_charge) + + stackHead := exp(a, exponent) + ip := add(ip, 1) } case 0x0B { // OP_SIGNEXTEND @@ -4456,14 +4458,16 @@ object "EvmEmulator" { popStackCheck(sp, 2) a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) - stackHead := exp(a, exponent) - let to_charge := 0 - for {} gt(exponent,0) {} { // while exponent > 0 + let exponentCopy := exponent + for {} gt(exponentCopy, 0) {} { // while exponent > 0 to_charge := add(to_charge, 50) - exponent := shr(8, exponent) + exponentCopy := shr(8, exponentCopy) } evmGasLeft := chargeGas(evmGasLeft, to_charge) + + stackHead := exp(a, exponent) + ip := add(ip, 1) } case 0x0B { // OP_SIGNEXTEND diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 5277f290c..113dcab08 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -116,14 +116,16 @@ for { } true { } { popStackCheck(sp, 2) a, sp, exponent := popStackItemWithoutCheck(sp, stackHead) - stackHead := exp(a, exponent) - let to_charge := 0 - for {} gt(exponent,0) {} { // while exponent > 0 + let exponentCopy := exponent + for {} gt(exponentCopy, 0) {} { // while exponent > 0 to_charge := add(to_charge, 50) - exponent := shr(8, exponent) + exponentCopy := shr(8, exponentCopy) } evmGasLeft := chargeGas(evmGasLeft, to_charge) + + stackHead := exp(a, exponent) + ip := add(ip, 1) } case 0x0B { // OP_SIGNEXTEND From 7b8cecc844baa39ade582f1e9b6b0eda24276cfb Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sat, 26 Oct 2024 13:22:28 +0200 Subject: [PATCH 105/183] fix(EVM): Make contract creation consistent with Geth implementation (#1008) --- system-contracts/SystemContractsHashes.json | 8 +- .../contracts/ContractDeployer.sol | 39 +- system-contracts/contracts/EvmEmulator.yul | 544 +++++++++--------- .../evm-emulator/EvmEmulator.template.yul | 18 +- .../EvmEmulatorFunctions.template.yul | 247 ++++---- .../evm-emulator/EvmEmulatorLoop.template.yul | 20 +- 6 files changed, 417 insertions(+), 459 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 6d2a9c8ee..420013feb 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": "0x010006893b07703146f0b1c9b4cd9d481e206eef99147d13fea699be2fdc8ad9", - "sourceCodeHash": "0xa4c2c1f55f5ef1281e18fd016865d9b83b71ad7facb2fd5130940b3b0b7de621" + "bytecodeHash": "0x01000697c616ad2f70268eedf874c28c7396a868e5a13f3b3401ed7693a9ec4d", + "sourceCodeHash": "0xa6ce082f01fa320322b961928086128e4f3dbd35928b8754f74e49c07c1db456" }, { "contractName": "Create2Factory", @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cf74eb8015735f39ee5568f6025c9e789d2d73c9b5510614e6296c87341", - "sourceCodeHash": "0xf5d31991d176ac5beca9190ae39fae9e17f32bfe78d4359d6c564959b5478868" + "bytecodeHash": "0x01000cd3259c135498bea6fabbd58c67187ff2effbbc8c3aa2e9a9358e79defc", + "sourceCodeHash": "0xe607a7ec66e349868419f82ffeb32063b46cb9bde7e85612c44ffd79a318ec08" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 2e1278d33..5c8d6e129 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -200,25 +200,30 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { return newAddress; } - function prepareForEvmCreateFromEmulator() public onlySystemCallFromEvmEmulator returns (address) { + function precreateEvmAccountFromEmulator( + bytes32 _salt, + bytes32 evmBytecodeHash + ) public onlySystemCallFromEvmEmulator returns (address newAddress) { if (_getAllowedBytecodeTypesMode() != AllowedBytecodeTypes.EraVmAndEVM) { revert EVMEmulationNotSupported(); } - return address(0); // TODO solidity semantic tests are invalid, remove it later - - // TODO uncomment - /* uint256 senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); - address newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); + if (evmBytecodeHash != bytes32(0)) { + // Create2 case + newAddress = Utils.getNewAddressCreate2EVM(msg.sender, _salt, evmBytecodeHash); + } else { + // Create case + newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); + } // Unfortunately we can not provide revert reason as it would break EVM compatibility + // we should not increase nonce in case of collision require(NONCE_HOLDER_SYSTEM_CONTRACT.getRawNonce(newAddress) == 0x0); require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.getCodeHash(uint256(uint160(newAddress))) == 0x0); return newAddress; - */ } /// Note: only possible revert case should be due to revert in the called constructor @@ -226,34 +231,20 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address newAddress, bytes calldata _initCode ) external payable onlySystemCallFromEvmEmulator returns (address) { - // ##### TODO solidity semantic tests are invalid, remove it later - { - uint256 senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); - - newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); - - // 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); - } - // ##### END TODO - _evmDeployOnAddress(msg.sender, 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. + /// Note: this method may be callable only in system mode function create2EVM( bytes32 _salt, bytes calldata _initCode ) external payable override onlySystemCall returns (address) { - // No collision is possible with the zksync's non-EVM CREATE2, since - // the prefixes are different + NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); + // 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); diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index c7c07049d..8579ad7cb 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -11,7 +11,7 @@ object "EvmEmulator" { let size := getActivePtrDataSize() - if gt(size, MAX_POSSIBLE_BYTECODE()) { + if gt(size, MAX_POSSIBLE_INIT_BYTECODE()) { panic() } @@ -40,15 +40,21 @@ object "EvmEmulator" { } } - function validateCorrectBytecode(offset, len, gasToReturn) -> returnGas { - if len { + function validateBytecodeAndChargeGas(offset, deployedCodeLen, gasToReturn) -> returnGas { + if deployedCodeLen { + // EIP-3860 + if gt(deployedCodeLen, MAX_POSSIBLE_DEPLOYED_BYTECODE()) { + panic() + } + + // EIP-3541 let firstByte := shr(248, mload(offset)) if eq(firstByte, 0xEF) { - revert(0, 0) + panic() } } - let gasForCode := mul(len, 200) + let gasForCode := mul(deployedCodeLen, 200) returnGas := chargeGas(gasToReturn, gasForCode) } @@ -92,12 +98,16 @@ object "EvmEmulator" { offset := add(STACK_OFFSET(), mul(1024, 32)) } - function MAX_POSSIBLE_BYTECODE() -> max { - max := 32000 + function MAX_POSSIBLE_DEPLOYED_BYTECODE() -> max { + max := 24576 + } + + function MAX_POSSIBLE_INIT_BYTECODE() -> max { + max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE()) // EIP-3860 } function MEM_OFFSET() -> offset { - offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_BYTECODE()) + offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_INIT_BYTECODE()) } function MEM_OFFSET_INNER() -> offset { @@ -125,9 +135,9 @@ object "EvmEmulator" { function EVM_GAS_STIPEND() -> gas_stipend { gas_stipend := shl(30, 1) } // 1 << 30 - // We need to pass some gas for MsgValueSimulator internal logic + // We need to pass some gas for MsgValueSimulator internal logic to decommit emulator etc function MSG_VALUE_SIMULATOR_STIPEND_GAS() -> gas_stipend { - gas_stipend := 30000 // 27000 + a little bit more + gas_stipend := 35000 // 27000 + a little bit more } function OVERHEAD() -> overhead { overhead := 2000 } @@ -328,7 +338,7 @@ object "EvmEmulator" { let codeLen := _fetchDeployedCode( getCodeAddress(), add(BYTECODE_OFFSET(), 32), - MAX_POSSIBLE_BYTECODE() + MAX_POSSIBLE_DEPLOYED_BYTECODE() ) mstore(BYTECODE_OFFSET(), codeLen) @@ -379,7 +389,19 @@ object "EvmEmulator" { function performSystemCall( to, dataLength, - ) -> ret { + ) { + let success := performSystemCallRevertable(to, dataLength) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + } + + function performSystemCallRevertable( + to, + dataLength, + ) -> success { let farCallAbi := shl(248, 1) // system call // dataOffset is 0 // dataStart is 0 @@ -389,12 +411,7 @@ object "EvmEmulator" { // forwardingMode is 0 // not constructor call - let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } + success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } function _isEVM(_addr) -> isEVM { @@ -1091,161 +1108,127 @@ object "EvmEmulator" { gasLeft := mload(0) } - function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { - _eraseReturndataPointer() + function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { + checkMemIsAccessible(offset, size) + + // EIP-3860 + if gt(size, MAX_POSSIBLE_INIT_BYTECODE()) { + panic() + } - let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) + // dynamicGas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost + // + hash_cost, if isCreate2 + // minimum_word_size = (size + 31) / 32 + // init_code_cost = 2 * minimum_word_size, EIP-3860 + // code_deposit_cost = 200 * deployed_code_size, (charged inside call) + let minimum_word_size := div(add(size, 31), 32) // rounding up + let dynamicGas := add( + mul(2, minimum_word_size), + expandMemory(add(offset, size)) + ) + if isCreate2 { + // hash_cost = 6 * minimum_word_size + dynamicGas := add(dynamicGas, mul(6, minimum_word_size)) + } + evmGasLeft := chargeGas(evmGasLeftOld, dynamicGas) - offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check + _eraseReturndataPointer() - pushStackCheck(sp, 4) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) + offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow - _pushEVMFrame(gasForTheCall, false) + let gasForTheCall := capGasForCall(evmGasLeft, INF_PASS_GAS()) - if isCreate2 { - // selector: create2EVM(bytes32 _salt, bytes calldata _initCode) - 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) + if gt(value, selfbalance()) { // it should be checked before actual deploy call + revertWithGas(evmGasLeft) // gasForTheCall not consumed + } - result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) + let bytecodeHash := 0 + if isCreate2 { + bytecodeHash := keccak256(offset, size) } + // we want to calculate the address of new contract, and if it is deployable (no collision), + // we need to increment deploy nonce. Otherwise - panic. + // We should revert with gas if nonce overflowed, but this should not happen in reality anyway - if iszero(isCreate2) { - if gt(value, selfbalance()) { // it should be checked before actual deploy call - panic() - } + // selector: function precreateEvmAccountFromEmulator(bytes32 salt, bytes32 evmBytecodeHash) + mstore(0, 0xf81dae8600000000000000000000000000000000000000000000000000000000) + mstore(4, salt) + mstore(36, bytecodeHash) + let precreateResult := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) - // we want to calculate the address of new contract - // and if it is deployable, we need to increment deploy nonce + if iszero(precreateResult) { + // collision, nonce overflow or EVM not allowed + // this is *internal* panic, consuming all passed gas + evmGasLeft := chargeGas(evmGasLeft, gasForTheCall) + } - // selector: function prepareForEvmCreateFromEmulator() - mstore(0, 0x3ec89a4e00000000000000000000000000000000000000000000000000000000) - performSystemCall(DEPLOYER_SYSTEM_CONTRACT(), 4) + if precreateResult { returndatacopy(0, 0, 32) addr := mload(0) + + pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) // will stay warm even if constructor reverts + // so even if constructor reverts, nonce stays incremented and addr stays warm + + // verification of the correctness of the deployed bytecode and payment of gas for its storage will occur in the frame of the new contract + _pushEVMFrame(gasForTheCall, false) - // so even if constructor reverts, nonce stays incremented - + // move needed memory slots to the scratch space + mstore(mul(10, 32), mload(sub(offset, 0x80)) + mstore(mul(11, 32), mload(sub(offset, 0x60)) + mstore(mul(12, 32), mload(sub(offset, 0x40)) + mstore(mul(13, 32), mload(sub(offset, 0x20)) + // selector: function createEvmFromEmulator(address newAddress, bytes calldata _initCode) mstore(sub(offset, 0x80), 0xe43cec64) - // address mstore(sub(offset, 0x60), addr) - // Where the arg starts (third word) - mstore(sub(offset, 0x40), 0x40) - // Length of the init code - mstore(sub(offset, 0x20), size) - - result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) - } - - let gasLeft - switch result - case 0 { - addr := 0 - gasLeft := _saveReturndataAfterEVMCall(0, 0) - } - default { - returndatacopy(0, 0, 32) - addr := mload(0) - gasLeft := _fetchConstructorReturnGas() - } - - let gasUsed := sub(gasForTheCall, gasLeft) - evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - - // moving memory slots back - let back + mstore(sub(offset, 0x40), 0x40) // Where the arg starts (third word) + mstore(sub(offset, 0x20), size) // Length of the init code - // skipping check since we pushed exactly 4 items earlier - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x20), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x40), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x60), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x80), back) - } - - function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { - evmGasLeft := chargeGas(evmGas, 32000) + let result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) - if isStatic { - panic() + // move memory slots back + mstore(sub(offset, 0x80), mload(mul(10, 32)) + mstore(sub(offset, 0x60), mload(mul(11, 32)) + mstore(sub(offset, 0x40), mload(mul(12, 32)) + mstore(sub(offset, 0x20), mload(mul(13, 32)) + + let gasLeft + switch result + case 0 { + addr := 0 + gasLeft := _saveReturndataAfterEVMCall(0, 0) + } + default { + returndatacopy(0, 0, 32) + addr := mload(0) + gasLeft := _fetchConstructorReturnGas() + } + + let gasUsed := sub(gasForTheCall, gasLeft) + evmGasLeft := chargeGas(evmGasLeft, gasUsed) } + } + function performCreate(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { let value, offset, size popStackCheck(oldSp, 3) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(offset, size) - - if gt(size, MAX_POSSIBLE_BYTECODE()) { - panic() - } - - // 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, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0, stackHead) - - switch result - case 0 { stackHead := 0 } - default { stackHead := addr } + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, false, 0) } - function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp, result, addr, stackHead { - evmGasLeft := chargeGas(evmGas, 32000) - - if isStatic { - panic() - } - + function performCreate2(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { let value, offset, size, salt popStackCheck(oldSp, 4) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, salt := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(offset, size) - - if gt(size, MAX_POSSIBLE_BYTECODE()) { - panic() - } - - // 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, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, true, salt, stackHead) + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, true, salt) } //////////////////////////////////////////////////////////////// @@ -2645,7 +2628,13 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0xF0 { // OP_CREATE - evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, isStatic, stackHead) + evmGasLeft := chargeGas(evmGasLeft, 32000) + + if isStatic { + panic() + } + + evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0xF1 { // OP_CALL @@ -2681,11 +2670,13 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 - let result, addr - evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) - switch result - case 0 { sp, stackHead := pushStackItem(sp, 0, stackHead) } - default { sp, stackHead := pushStackItem(sp, addr, stackHead) } + evmGasLeft := chargeGas(evmGasLeft, 32000) + + if isStatic { + panic() + } + + evmGasLeft, sp, stackHead := performCreate2(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0xFA { // OP_STATICCALL @@ -3082,7 +3073,7 @@ object "EvmEmulator" { let offset, len, gasToReturn := simulate(isCallerEVM, evmGasLeft, false) - gasToReturn := validateCorrectBytecode(offset, len, gasToReturn) + gasToReturn := validateBytecodeAndChargeGas(offset, len, gasToReturn) offset, len := padBytecode(offset, len) @@ -3132,12 +3123,16 @@ object "EvmEmulator" { offset := add(STACK_OFFSET(), mul(1024, 32)) } - function MAX_POSSIBLE_BYTECODE() -> max { - max := 32000 + function MAX_POSSIBLE_DEPLOYED_BYTECODE() -> max { + max := 24576 + } + + function MAX_POSSIBLE_INIT_BYTECODE() -> max { + max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE()) // EIP-3860 } function MEM_OFFSET() -> offset { - offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_BYTECODE()) + offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_INIT_BYTECODE()) } function MEM_OFFSET_INNER() -> offset { @@ -3165,9 +3160,9 @@ object "EvmEmulator" { function EVM_GAS_STIPEND() -> gas_stipend { gas_stipend := shl(30, 1) } // 1 << 30 - // We need to pass some gas for MsgValueSimulator internal logic + // We need to pass some gas for MsgValueSimulator internal logic to decommit emulator etc function MSG_VALUE_SIMULATOR_STIPEND_GAS() -> gas_stipend { - gas_stipend := 30000 // 27000 + a little bit more + gas_stipend := 35000 // 27000 + a little bit more } function OVERHEAD() -> overhead { overhead := 2000 } @@ -3368,7 +3363,7 @@ object "EvmEmulator" { let codeLen := _fetchDeployedCode( getCodeAddress(), add(BYTECODE_OFFSET(), 32), - MAX_POSSIBLE_BYTECODE() + MAX_POSSIBLE_DEPLOYED_BYTECODE() ) mstore(BYTECODE_OFFSET(), codeLen) @@ -3419,7 +3414,19 @@ object "EvmEmulator" { function performSystemCall( to, dataLength, - ) -> ret { + ) { + let success := performSystemCallRevertable(to, dataLength) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + } + + function performSystemCallRevertable( + to, + dataLength, + ) -> success { let farCallAbi := shl(248, 1) // system call // dataOffset is 0 // dataStart is 0 @@ -3429,12 +3436,7 @@ object "EvmEmulator" { // forwardingMode is 0 // not constructor call - let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } + success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } function _isEVM(_addr) -> isEVM { @@ -4131,161 +4133,127 @@ object "EvmEmulator" { gasLeft := mload(0) } - function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { - _eraseReturndataPointer() + function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { + checkMemIsAccessible(offset, size) + + // EIP-3860 + if gt(size, MAX_POSSIBLE_INIT_BYTECODE()) { + panic() + } + + // dynamicGas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost + // + hash_cost, if isCreate2 + // minimum_word_size = (size + 31) / 32 + // init_code_cost = 2 * minimum_word_size, EIP-3860 + // code_deposit_cost = 200 * deployed_code_size, (charged inside call) + let minimum_word_size := div(add(size, 31), 32) // rounding up + let dynamicGas := add( + mul(2, minimum_word_size), + expandMemory(add(offset, size)) + ) + if isCreate2 { + // hash_cost = 6 * minimum_word_size + dynamicGas := add(dynamicGas, mul(6, minimum_word_size)) + } + evmGasLeft := chargeGas(evmGasLeftOld, dynamicGas) - let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) + _eraseReturndataPointer() - offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check + offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow - pushStackCheck(sp, 4) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) + let gasForTheCall := capGasForCall(evmGasLeft, INF_PASS_GAS()) - _pushEVMFrame(gasForTheCall, false) + if gt(value, selfbalance()) { // it should be checked before actual deploy call + revertWithGas(evmGasLeft) // gasForTheCall not consumed + } + let bytecodeHash := 0 if isCreate2 { - // selector: create2EVM(bytes32 _salt, bytes calldata _initCode) - 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 := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) + bytecodeHash := keccak256(offset, size) } + // we want to calculate the address of new contract, and if it is deployable (no collision), + // we need to increment deploy nonce. Otherwise - panic. + // We should revert with gas if nonce overflowed, but this should not happen in reality anyway - if iszero(isCreate2) { - if gt(value, selfbalance()) { // it should be checked before actual deploy call - panic() - } + // selector: function precreateEvmAccountFromEmulator(bytes32 salt, bytes32 evmBytecodeHash) + mstore(0, 0xf81dae8600000000000000000000000000000000000000000000000000000000) + mstore(4, salt) + mstore(36, bytecodeHash) + let precreateResult := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) - // we want to calculate the address of new contract - // and if it is deployable, we need to increment deploy nonce + if iszero(precreateResult) { + // collision, nonce overflow or EVM not allowed + // this is *internal* panic, consuming all passed gas + evmGasLeft := chargeGas(evmGasLeft, gasForTheCall) + } - // selector: function prepareForEvmCreateFromEmulator() - mstore(0, 0x3ec89a4e00000000000000000000000000000000000000000000000000000000) - performSystemCall(DEPLOYER_SYSTEM_CONTRACT(), 4) + if precreateResult { returndatacopy(0, 0, 32) addr := mload(0) + + pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) // will stay warm even if constructor reverts + // so even if constructor reverts, nonce stays incremented and addr stays warm + + // verification of the correctness of the deployed bytecode and payment of gas for its storage will occur in the frame of the new contract + _pushEVMFrame(gasForTheCall, false) - // so even if constructor reverts, nonce stays incremented - + // move needed memory slots to the scratch space + mstore(mul(10, 32), mload(sub(offset, 0x80)) + mstore(mul(11, 32), mload(sub(offset, 0x60)) + mstore(mul(12, 32), mload(sub(offset, 0x40)) + mstore(mul(13, 32), mload(sub(offset, 0x20)) + // selector: function createEvmFromEmulator(address newAddress, bytes calldata _initCode) mstore(sub(offset, 0x80), 0xe43cec64) - // address mstore(sub(offset, 0x60), addr) - // Where the arg starts (third word) - mstore(sub(offset, 0x40), 0x40) - // Length of the init code - mstore(sub(offset, 0x20), size) - - result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) - } - - let gasLeft - switch result - case 0 { - addr := 0 - gasLeft := _saveReturndataAfterEVMCall(0, 0) - } - default { - returndatacopy(0, 0, 32) - addr := mload(0) - gasLeft := _fetchConstructorReturnGas() - } - - let gasUsed := sub(gasForTheCall, gasLeft) - evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - - // moving memory slots back - let back + mstore(sub(offset, 0x40), 0x40) // Where the arg starts (third word) + mstore(sub(offset, 0x20), size) // Length of the init code - // skipping check since we pushed exactly 4 items earlier - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x20), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x40), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x60), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x80), back) - } + let result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) - function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { - evmGasLeft := chargeGas(evmGas, 32000) - - if isStatic { - panic() + // move memory slots back + mstore(sub(offset, 0x80), mload(mul(10, 32)) + mstore(sub(offset, 0x60), mload(mul(11, 32)) + mstore(sub(offset, 0x40), mload(mul(12, 32)) + mstore(sub(offset, 0x20), mload(mul(13, 32)) + + let gasLeft + switch result + case 0 { + addr := 0 + gasLeft := _saveReturndataAfterEVMCall(0, 0) + } + default { + returndatacopy(0, 0, 32) + addr := mload(0) + gasLeft := _fetchConstructorReturnGas() + } + + let gasUsed := sub(gasForTheCall, gasLeft) + evmGasLeft := chargeGas(evmGasLeft, gasUsed) } + } + function performCreate(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { let value, offset, size popStackCheck(oldSp, 3) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(offset, size) - - if gt(size, MAX_POSSIBLE_BYTECODE()) { - panic() - } - - // 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, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0, stackHead) - - switch result - case 0 { stackHead := 0 } - default { stackHead := addr } + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, false, 0) } - function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp, result, addr, stackHead { - evmGasLeft := chargeGas(evmGas, 32000) - - if isStatic { - panic() - } - + function performCreate2(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { let value, offset, size, salt popStackCheck(oldSp, 4) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - if gt(size, MAX_POSSIBLE_BYTECODE()) { - panic() - } + size, sp, salt := popStackItemWithoutCheck(sp, stackHead) - // 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, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, true, salt, stackHead) + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, true, salt) } //////////////////////////////////////////////////////////////// @@ -5685,7 +5653,13 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0xF0 { // OP_CREATE - evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, isStatic, stackHead) + evmGasLeft := chargeGas(evmGasLeft, 32000) + + if isStatic { + panic() + } + + evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0xF1 { // OP_CALL @@ -5721,11 +5695,13 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 - let result, addr - evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) - switch result - case 0 { sp, stackHead := pushStackItem(sp, 0, stackHead) } - default { sp, stackHead := pushStackItem(sp, addr, stackHead) } + evmGasLeft := chargeGas(evmGasLeft, 32000) + + if isStatic { + panic() + } + + evmGasLeft, sp, stackHead := performCreate2(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0xFA { // OP_STATICCALL diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index e6eee5b35..1730a0b8e 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -11,7 +11,7 @@ object "EvmEmulator" { let size := getActivePtrDataSize() - if gt(size, MAX_POSSIBLE_BYTECODE()) { + if gt(size, MAX_POSSIBLE_INIT_BYTECODE()) { panic() } @@ -40,15 +40,21 @@ object "EvmEmulator" { } } - function validateCorrectBytecode(offset, len, gasToReturn) -> returnGas { - if len { + function validateBytecodeAndChargeGas(offset, deployedCodeLen, gasToReturn) -> returnGas { + if deployedCodeLen { + // EIP-3860 + if gt(deployedCodeLen, MAX_POSSIBLE_DEPLOYED_BYTECODE()) { + panic() + } + + // EIP-3541 let firstByte := shr(248, mload(offset)) if eq(firstByte, 0xEF) { - revert(0, 0) + panic() } } - let gasForCode := mul(len, 200) + let gasForCode := mul(deployedCodeLen, 200) returnGas := chargeGas(gasToReturn, gasForCode) } @@ -88,7 +94,7 @@ object "EvmEmulator" { let offset, len, gasToReturn := simulate(isCallerEVM, evmGasLeft, false) - gasToReturn := validateCorrectBytecode(offset, len, gasToReturn) + gasToReturn := validateBytecodeAndChargeGas(offset, len, gasToReturn) offset, len := padBytecode(offset, len) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index de18a50f4..b81356bfb 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -38,12 +38,16 @@ function BYTECODE_OFFSET() -> offset { offset := add(STACK_OFFSET(), mul(1024, 32)) } -function MAX_POSSIBLE_BYTECODE() -> max { - max := 32000 +function MAX_POSSIBLE_DEPLOYED_BYTECODE() -> max { + max := 24576 +} + +function MAX_POSSIBLE_INIT_BYTECODE() -> max { + max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE()) // EIP-3860 } function MEM_OFFSET() -> offset { - offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_BYTECODE()) + offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_INIT_BYTECODE()) } function MEM_OFFSET_INNER() -> offset { @@ -71,9 +75,9 @@ function GAS_DIVISOR() -> gas_div { gas_div := 5 } function EVM_GAS_STIPEND() -> gas_stipend { gas_stipend := shl(30, 1) } // 1 << 30 -// We need to pass some gas for MsgValueSimulator internal logic +// We need to pass some gas for MsgValueSimulator internal logic to decommit emulator etc function MSG_VALUE_SIMULATOR_STIPEND_GAS() -> gas_stipend { - gas_stipend := 30000 // 27000 + a little bit more + gas_stipend := 35000 // 27000 + a little bit more } function OVERHEAD() -> overhead { overhead := 2000 } @@ -274,7 +278,7 @@ function getDeployedBytecode() { let codeLen := _fetchDeployedCode( getCodeAddress(), add(BYTECODE_OFFSET(), 32), - MAX_POSSIBLE_BYTECODE() + MAX_POSSIBLE_DEPLOYED_BYTECODE() ) mstore(BYTECODE_OFFSET(), codeLen) @@ -325,7 +329,19 @@ function expandMemory(newSize) -> gasCost { function performSystemCall( to, dataLength, -) -> ret { +) { + let success := performSystemCallRevertable(to, dataLength) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } +} + +function performSystemCallRevertable( + to, + dataLength, +) -> success { let farCallAbi := shl(248, 1) // system call // dataOffset is 0 // dataStart is 0 @@ -335,12 +351,7 @@ function performSystemCall( // forwardingMode is 0 // not constructor call - let success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } + success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } function _isEVM(_addr) -> isEVM { @@ -1037,161 +1048,127 @@ function _fetchConstructorReturnGas() -> gasLeft { gasLeft := mload(0) } -function $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeftOld, isCreate2, salt, oldStackHead) -> result, evmGasLeft, addr, stackHead { - _eraseReturndataPointer() +function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { + checkMemIsAccessible(offset, size) - let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) + // EIP-3860 + if gt(size, MAX_POSSIBLE_INIT_BYTECODE()) { + panic() + } - offset := add(MEM_OFFSET_INNER(), offset) // TODO gas check + // dynamicGas = init_code_cost + memory_expansion_cost + deployment_code_execution_cost + code_deposit_cost + // + hash_cost, if isCreate2 + // minimum_word_size = (size + 31) / 32 + // init_code_cost = 2 * minimum_word_size, EIP-3860 + // code_deposit_cost = 200 * deployed_code_size, (charged inside call) + let minimum_word_size := div(add(size, 31), 32) // rounding up + let dynamicGas := add( + mul(2, minimum_word_size), + expandMemory(add(offset, size)) + ) + if isCreate2 { + // hash_cost = 6 * minimum_word_size + dynamicGas := add(dynamicGas, mul(6, minimum_word_size)) + } + evmGasLeft := chargeGas(evmGasLeftOld, dynamicGas) - pushStackCheck(sp, 4) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x80)), oldStackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x60)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x40)), stackHead) - sp, stackHead := pushStackItemWithoutCheck(sp, mload(sub(offset, 0x20)), stackHead) + _eraseReturndataPointer() - _pushEVMFrame(gasForTheCall, false) + offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow - if isCreate2 { - // selector: create2EVM(bytes32 _salt, bytes calldata _initCode) - 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) + let gasForTheCall := capGasForCall(evmGasLeft, INF_PASS_GAS()) - result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) + if gt(value, selfbalance()) { // it should be checked before actual deploy call + revertWithGas(evmGasLeft) // gasForTheCall not consumed } + let bytecodeHash := 0 + if isCreate2 { + bytecodeHash := keccak256(offset, size) + } - if iszero(isCreate2) { - if gt(value, selfbalance()) { // it should be checked before actual deploy call - panic() - } + // we want to calculate the address of new contract, and if it is deployable (no collision), + // we need to increment deploy nonce. Otherwise - panic. + // We should revert with gas if nonce overflowed, but this should not happen in reality anyway - // we want to calculate the address of new contract - // and if it is deployable, we need to increment deploy nonce + // selector: function precreateEvmAccountFromEmulator(bytes32 salt, bytes32 evmBytecodeHash) + mstore(0, 0xf81dae8600000000000000000000000000000000000000000000000000000000) + mstore(4, salt) + mstore(36, bytecodeHash) + let precreateResult := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) - // selector: function prepareForEvmCreateFromEmulator() - mstore(0, 0x3ec89a4e00000000000000000000000000000000000000000000000000000000) - performSystemCall(DEPLOYER_SYSTEM_CONTRACT(), 4) + if iszero(precreateResult) { + // collision, nonce overflow or EVM not allowed + // this is *internal* panic, consuming all passed gas + evmGasLeft := chargeGas(evmGasLeft, gasForTheCall) + } + + if precreateResult { returndatacopy(0, 0, 32) addr := mload(0) - - // so even if constructor reverts, nonce stays incremented - + + pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) // will stay warm even if constructor reverts + // so even if constructor reverts, nonce stays incremented and addr stays warm + + // verification of the correctness of the deployed bytecode and payment of gas for its storage will occur in the frame of the new contract + _pushEVMFrame(gasForTheCall, false) + + // move needed memory slots to the scratch space + mstore(mul(10, 32), mload(sub(offset, 0x80)) + mstore(mul(11, 32), mload(sub(offset, 0x60)) + mstore(mul(12, 32), mload(sub(offset, 0x40)) + mstore(mul(13, 32), mload(sub(offset, 0x20)) + // selector: function createEvmFromEmulator(address newAddress, bytes calldata _initCode) mstore(sub(offset, 0x80), 0xe43cec64) - // address mstore(sub(offset, 0x60), addr) - // Where the arg starts (third word) - mstore(sub(offset, 0x40), 0x40) - // Length of the init code - mstore(sub(offset, 0x20), size) - - result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) - } - - let gasLeft - switch result - case 0 { - addr := 0 - gasLeft := _saveReturndataAfterEVMCall(0, 0) - } - default { - returndatacopy(0, 0, 32) - addr := mload(0) - gasLeft := _fetchConstructorReturnGas() - } - - let gasUsed := sub(gasForTheCall, gasLeft) - evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) - - // moving memory slots back - let back + mstore(sub(offset, 0x40), 0x40) // Where the arg starts (third word) + mstore(sub(offset, 0x20), size) // Length of the init code - // skipping check since we pushed exactly 4 items earlier - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x20), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x40), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x60), back) - back, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - mstore(sub(offset, 0x80), back) -} - -function performCreate(evmGas,oldSp,isStatic, oldStackHead) -> evmGasLeft, sp, stackHead { - evmGasLeft := chargeGas(evmGas, 32000) - - if isStatic { - panic() + let result := performSystemCallForCreate(value, sub(offset, 0x64), add(size, 0x64)) + + // move memory slots back + mstore(sub(offset, 0x80), mload(mul(10, 32)) + mstore(sub(offset, 0x60), mload(mul(11, 32)) + mstore(sub(offset, 0x40), mload(mul(12, 32)) + mstore(sub(offset, 0x20), mload(mul(13, 32)) + + let gasLeft + switch result + case 0 { + addr := 0 + gasLeft := _saveReturndataAfterEVMCall(0, 0) + } + default { + returndatacopy(0, 0, 32) + addr := mload(0) + gasLeft := _fetchConstructorReturnGas() + } + + let gasUsed := sub(gasForTheCall, gasLeft) + evmGasLeft := chargeGas(evmGasLeft, gasUsed) } +} +function performCreate(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { let value, offset, size popStackCheck(oldSp, 3) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(offset, size) - - if gt(size, MAX_POSSIBLE_BYTECODE()) { - panic() - } - - // 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, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, false, 0, stackHead) - - switch result - case 0 { stackHead := 0 } - default { stackHead := addr } + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, false, 0) } -function performCreate2(evmGas, oldSp, isStatic, oldStackHead) -> evmGasLeft, sp, result, addr, stackHead { - evmGasLeft := chargeGas(evmGas, 32000) - - if isStatic { - panic() - } - +function performCreate2(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { let value, offset, size, salt popStackCheck(oldSp, 4) value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - salt, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) + size, sp, salt := popStackItemWithoutCheck(sp, stackHead) - if gt(size, MAX_POSSIBLE_BYTECODE()) { - panic() - } - - // 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, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, sp, value, evmGasLeft, true, salt, stackHead) + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, true, salt) } //////////////////////////////////////////////////////////////// diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 113dcab08..d9f388c31 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -1343,7 +1343,13 @@ for { } true { } { ip := add(ip, 1) } case 0xF0 { // OP_CREATE - evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, isStatic, stackHead) + evmGasLeft := chargeGas(evmGasLeft, 32000) + + if isStatic { + panic() + } + + evmGasLeft, sp, stackHead := performCreate(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0xF1 { // OP_CALL @@ -1379,11 +1385,13 @@ for { } true { } { ip := add(ip, 1) } case 0xF5 { // OP_CREATE2 - let result, addr - evmGasLeft, sp, result, addr, stackHead := performCreate2(evmGasLeft, sp, isStatic, stackHead) - switch result - case 0 { sp, stackHead := pushStackItem(sp, 0, stackHead) } - default { sp, stackHead := pushStackItem(sp, addr, stackHead) } + evmGasLeft := chargeGas(evmGasLeft, 32000) + + if isStatic { + panic() + } + + evmGasLeft, sp, stackHead := performCreate2(evmGasLeft, sp, stackHead) ip := add(ip, 1) } case 0xFA { // OP_STATICCALL From f6809c0ed4c8aaba30ce2c09612586190ea834bd Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sat, 26 Oct 2024 14:02:08 +0200 Subject: [PATCH 106/183] fix(EVM): Fix expand memory (#1002) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 162 ++++++++++-------- .../EvmEmulatorFunctions.template.yul | 50 ++++-- .../evm-emulator/EvmEmulatorLoop.template.yul | 30 ++-- 4 files changed, 141 insertions(+), 105 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 420013feb..bfc85b78e 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cd3259c135498bea6fabbd58c67187ff2effbbc8c3aa2e9a9358e79defc", - "sourceCodeHash": "0xe607a7ec66e349868419f82ffeb32063b46cb9bde7e85612c44ffd79a318ec08" + "bytecodeHash": "0x01000d1d093f6a59a05b49ed5299ba34bb00dbac6f9bb3202f674dd73e3c8b47", + "sourceCodeHash": "0x1cf23b0864e4a958d66a7e2b74535478f866d61fd5af55651822d1565d5b5fb9" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 8579ad7cb..893e56f8a 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -368,21 +368,34 @@ object "EvmEmulator" { // 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)) + function expandMemory(offset, size) -> gasCost { + // memory expansion costs 0 if size is 0 + if size { + let oldSizeInWords := mload(MEM_OFFSET()) - mstore(MEM_OFFSET(), newSizeInWords) + // div rounding up + let newSizeInWords := div(add(add(offset, size), 31), 32) + + // memory_size_word = (memory_byte_size + 31) / 32 + // memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word) + // memory_expansion_cost = new_memory_cost - last_memory_cost + if gt(newSizeInWords, oldSizeInWords) { + let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords)) + let quadraticPart := sub( + div( + mul(newSizeInWords, newSizeInWords), + 512 + ), + div( + mul(oldSizeInWords, oldSizeInWords), + 512 + ) + ) + + gasCost := add(linearPart, quadraticPart) + + mstore(MEM_OFFSET(), newSizeInWords) + } } } @@ -874,13 +887,12 @@ object "EvmEmulator" { } function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> maxExpand { - maxExpand := add(retOffset, retSize) - switch lt(maxExpand, add(argsOffset, argsSize)) + switch lt(add(retOffset, retSize), add(argsOffset, argsSize)) case 0 { - maxExpand := expandMemory(maxExpand) + maxExpand := expandMemory(retOffset, retSize) } default { - maxExpand := expandMemory(add(argsOffset, argsSize)) + maxExpand := expandMemory(argsOffset, argsSize) } } @@ -1124,7 +1136,7 @@ object "EvmEmulator" { let minimum_word_size := div(add(size, 31), 32) // rounding up let dynamicGas := add( mul(2, minimum_word_size), - expandMemory(add(offset, size)) + expandMemory(offset, size) ) if isCreate2 { // hash_cost = 6 * minimum_word_size @@ -1575,7 +1587,7 @@ object "EvmEmulator" { // 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))) + let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) stackHead := keccak256(add(MEM_OFFSET_INNER(), offset), size) @@ -1647,7 +1659,7 @@ object "EvmEmulator" { // 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))) + let dynamicGas := add(mul(3, shr(5, add(size, 31))), expandMemory(destOffset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) calldatacopy(add(destOffset, MEM_OFFSET_INNER()), offset, size) @@ -1676,7 +1688,7 @@ object "EvmEmulator" { // 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(dstOffset, len))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) dstOffset := add(dstOffset, MEM_OFFSET_INNER()) @@ -1729,7 +1741,7 @@ object "EvmEmulator" { // minimum_word_size = (size + 31) / 32 let dynamicGas := add( mul(3, shr(5, add(len, 31))), - expandMemory(add(dest, len)) + expandMemory(dest, len) ) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -1767,7 +1779,7 @@ object "EvmEmulator" { // minimum_word_size = (size + 31) / 32 // dynamicGas = 3 * minimum_word_size + memory_expansion_cost - let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dstOffset, len))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) checkOverflow(sourceOffset, len) @@ -1858,7 +1870,7 @@ object "EvmEmulator" { let offset := accessStackHead(sp, stackHead) checkMemIsAccessible(offset, 32) - let expansionGas := expandMemory(add(offset, 32)) + let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) stackHead := mload(add(MEM_OFFSET_INNER(), offset)) @@ -1875,7 +1887,7 @@ object "EvmEmulator" { value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemIsAccessible(offset, 32) - let expansionGas := expandMemory(add(offset, 32)) + let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) mstore(add(MEM_OFFSET_INNER(), offset), value) @@ -1891,7 +1903,7 @@ object "EvmEmulator" { value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemIsAccessible(offset, 1) - let expansionGas := expandMemory(add(offset, 1)) + let expansionGas := expandMemory(offset, 1) evmGasLeft := chargeGas(evmGasLeft, expansionGas) mstore8(add(MEM_OFFSET_INNER(), offset), value) @@ -2511,7 +2523,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) log0(add(offset, MEM_OFFSET_INNER()), size) @@ -2532,7 +2544,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 375) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -2558,7 +2570,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 750) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -2585,7 +2597,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 1125) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -2613,7 +2625,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 1500) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -2657,7 +2669,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) returnLen := size @@ -2691,7 +2703,7 @@ object "EvmEmulator" { size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) // Don't check overflow here since previous checks are enough to ensure this is safe offset := add(offset, MEM_OFFSET_INNER()) @@ -3393,21 +3405,34 @@ object "EvmEmulator" { // 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) + function expandMemory(offset, size) -> gasCost { + // memory expansion costs 0 if size is 0 + if size { + let oldSizeInWords := mload(MEM_OFFSET()) + + // div rounding up + let newSizeInWords := div(add(add(offset, size), 31), 32) + + // memory_size_word = (memory_byte_size + 31) / 32 + // memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word) + // memory_expansion_cost = new_memory_cost - last_memory_cost + if gt(newSizeInWords, oldSizeInWords) { + let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords)) + let quadraticPart := sub( + div( + mul(newSizeInWords, newSizeInWords), + 512 + ), + div( + mul(oldSizeInWords, oldSizeInWords), + 512 + ) + ) + + gasCost := add(linearPart, quadraticPart) + + mstore(MEM_OFFSET(), newSizeInWords) + } } } @@ -3899,13 +3924,12 @@ object "EvmEmulator" { } function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> maxExpand { - maxExpand := add(retOffset, retSize) - switch lt(maxExpand, add(argsOffset, argsSize)) + switch lt(add(retOffset, retSize), add(argsOffset, argsSize)) case 0 { - maxExpand := expandMemory(maxExpand) + maxExpand := expandMemory(retOffset, retSize) } default { - maxExpand := expandMemory(add(argsOffset, argsSize)) + maxExpand := expandMemory(argsOffset, argsSize) } } @@ -4149,7 +4173,7 @@ object "EvmEmulator" { let minimum_word_size := div(add(size, 31), 32) // rounding up let dynamicGas := add( mul(2, minimum_word_size), - expandMemory(add(offset, size)) + expandMemory(offset, size) ) if isCreate2 { // hash_cost = 6 * minimum_word_size @@ -4600,7 +4624,7 @@ object "EvmEmulator" { // 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))) + let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) stackHead := keccak256(add(MEM_OFFSET_INNER(), offset), size) @@ -4672,7 +4696,7 @@ object "EvmEmulator" { // 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))) + let dynamicGas := add(mul(3, shr(5, add(size, 31))), expandMemory(destOffset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) calldatacopy(add(destOffset, MEM_OFFSET_INNER()), offset, size) @@ -4701,7 +4725,7 @@ object "EvmEmulator" { // 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(dstOffset, len))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) dstOffset := add(dstOffset, MEM_OFFSET_INNER()) @@ -4754,7 +4778,7 @@ object "EvmEmulator" { // minimum_word_size = (size + 31) / 32 let dynamicGas := add( mul(3, shr(5, add(len, 31))), - expandMemory(add(dest, len)) + expandMemory(dest, len) ) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -4792,7 +4816,7 @@ object "EvmEmulator" { // minimum_word_size = (size + 31) / 32 // dynamicGas = 3 * minimum_word_size + memory_expansion_cost - let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dstOffset, len))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) checkOverflow(sourceOffset, len) @@ -4883,7 +4907,7 @@ object "EvmEmulator" { let offset := accessStackHead(sp, stackHead) checkMemIsAccessible(offset, 32) - let expansionGas := expandMemory(add(offset, 32)) + let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) stackHead := mload(add(MEM_OFFSET_INNER(), offset)) @@ -4900,7 +4924,7 @@ object "EvmEmulator" { value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemIsAccessible(offset, 32) - let expansionGas := expandMemory(add(offset, 32)) + let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) mstore(add(MEM_OFFSET_INNER(), offset), value) @@ -4916,7 +4940,7 @@ object "EvmEmulator" { value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemIsAccessible(offset, 1) - let expansionGas := expandMemory(add(offset, 1)) + let expansionGas := expandMemory(offset, 1) evmGasLeft := chargeGas(evmGasLeft, expansionGas) mstore8(add(MEM_OFFSET_INNER(), offset), value) @@ -5536,7 +5560,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) log0(add(offset, MEM_OFFSET_INNER()), size) @@ -5557,7 +5581,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 375) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -5583,7 +5607,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 750) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -5610,7 +5634,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 1125) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -5638,7 +5662,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 1500) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -5682,7 +5706,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) returnLen := size @@ -5716,7 +5740,7 @@ object "EvmEmulator" { size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) // Don't check overflow here since previous checks are enough to ensure this is safe offset := add(offset, MEM_OFFSET_INNER()) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index b81356bfb..0a716511a 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -308,21 +308,34 @@ function bitMaskFromBytes(nBytes) -> bitMask { // 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()) +function expandMemory(offset, size) -> gasCost { + // memory expansion costs 0 if size is 0 + if size { + 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) + // div rounding up + let newSizeInWords := div(add(add(offset, size), 31), 32) + + // memory_size_word = (memory_byte_size + 31) / 32 + // memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word) + // memory_expansion_cost = new_memory_cost - last_memory_cost + if gt(newSizeInWords, oldSizeInWords) { + let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords)) + let quadraticPart := sub( + div( + mul(newSizeInWords, newSizeInWords), + 512 + ), + div( + mul(oldSizeInWords, oldSizeInWords), + 512 + ) + ) + + gasCost := add(linearPart, quadraticPart) + + mstore(MEM_OFFSET(), newSizeInWords) + } } } @@ -814,13 +827,12 @@ function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { } function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> maxExpand { - maxExpand := add(retOffset, retSize) - switch lt(maxExpand, add(argsOffset, argsSize)) + switch lt(add(retOffset, retSize), add(argsOffset, argsSize)) case 0 { - maxExpand := expandMemory(maxExpand) + maxExpand := expandMemory(retOffset, retSize) } default { - maxExpand := expandMemory(add(argsOffset, argsSize)) + maxExpand := expandMemory(argsOffset, argsSize) } } @@ -1064,7 +1076,7 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, let minimum_word_size := div(add(size, 31), 32) // rounding up let dynamicGas := add( mul(2, minimum_word_size), - expandMemory(add(offset, size)) + expandMemory(offset, size) ) if isCreate2 { // hash_cost = 6 * minimum_word_size diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index d9f388c31..c3bd57186 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -290,7 +290,7 @@ for { } true { } { // 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))) + let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) stackHead := keccak256(add(MEM_OFFSET_INNER(), offset), size) @@ -362,7 +362,7 @@ for { } true { } { // 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))) + let dynamicGas := add(mul(3, shr(5, add(size, 31))), expandMemory(destOffset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) calldatacopy(add(destOffset, MEM_OFFSET_INNER()), offset, size) @@ -391,7 +391,7 @@ for { } true { } { // 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(dstOffset, len))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) dstOffset := add(dstOffset, MEM_OFFSET_INNER()) @@ -444,7 +444,7 @@ for { } true { } { // minimum_word_size = (size + 31) / 32 let dynamicGas := add( mul(3, shr(5, add(len, 31))), - expandMemory(add(dest, len)) + expandMemory(dest, len) ) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -482,7 +482,7 @@ for { } true { } { // minimum_word_size = (size + 31) / 32 // dynamicGas = 3 * minimum_word_size + memory_expansion_cost - let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(add(dstOffset, len))) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) checkOverflow(sourceOffset, len) @@ -573,7 +573,7 @@ for { } true { } { let offset := accessStackHead(sp, stackHead) checkMemIsAccessible(offset, 32) - let expansionGas := expandMemory(add(offset, 32)) + let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) stackHead := mload(add(MEM_OFFSET_INNER(), offset)) @@ -590,7 +590,7 @@ for { } true { } { value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemIsAccessible(offset, 32) - let expansionGas := expandMemory(add(offset, 32)) + let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) mstore(add(MEM_OFFSET_INNER(), offset), value) @@ -606,7 +606,7 @@ for { } true { } { value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemIsAccessible(offset, 1) - let expansionGas := expandMemory(add(offset, 1)) + let expansionGas := expandMemory(offset, 1) evmGasLeft := chargeGas(evmGasLeft, expansionGas) mstore8(add(MEM_OFFSET_INNER(), offset), value) @@ -1226,7 +1226,7 @@ for { } true { } { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) log0(add(offset, MEM_OFFSET_INNER()), size) @@ -1247,7 +1247,7 @@ for { } true { } { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 375) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -1273,7 +1273,7 @@ for { } true { } { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 750) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -1300,7 +1300,7 @@ for { } true { } { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 1125) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -1328,7 +1328,7 @@ for { } true { } { checkMemIsAccessible(offset, size) // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(add(offset, size))) + let dynamicGas := add(shl(3, size), expandMemory(offset, size)) dynamicGas := add(dynamicGas, 1500) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) @@ -1372,7 +1372,7 @@ for { } true { } { checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) returnLen := size @@ -1406,7 +1406,7 @@ for { } true { } { size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(add(offset, size))) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) // Don't check overflow here since previous checks are enough to ensure this is safe offset := add(offset, MEM_OFFSET_INNER()) From 101646f49e4b4b364773255da4fad02b60823e33 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sat, 26 Oct 2024 14:48:06 +0200 Subject: [PATCH 107/183] fix(EVM): Update max posible mem to 4 MB (#1009) --- system-contracts/SystemContractsHashes.json | 4 ++-- system-contracts/contracts/EvmEmulator.yul | 20 ++++++------------- .../EvmEmulatorFunctions.template.yul | 10 +++------- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index bfc85b78e..445827b74 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000d1d093f6a59a05b49ed5299ba34bb00dbac6f9bb3202f674dd73e3c8b47", - "sourceCodeHash": "0x1cf23b0864e4a958d66a7e2b74535478f866d61fd5af55651822d1565d5b5fb9" + "bytecodeHash": "0x01000d1d757b324579b300119cd16596a2a38dd855441a96332be81c741d08ea", + "sourceCodeHash": "0xefaa64a7e279961887feecbb6486964ecf1755ef5b9898881fb5fdcd04cd7419" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 893e56f8a..9c4377428 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -114,8 +114,10 @@ object "EvmEmulator" { offset := add(MEM_OFFSET(), 32) } + // Used to simplify gas calculations for memory expansion. + // The cost to increase the memory to 4 MB is close to 30M gas function MAX_POSSIBLE_MEM() -> max { - max := 0x100000 // 1MB + max := 0x400000 // 4MB } function MAX_MEMORY_FRAME() -> max { @@ -181,12 +183,6 @@ object "EvmEmulator" { } } - function checkMemOverflow(location) { - if gt(location, MAX_MEMORY_FRAME()) { - panic() - } - } - function checkOverflow(data1, data2) { if lt(add(data1, data2), data2) { panic() @@ -3151,8 +3147,10 @@ object "EvmEmulator" { offset := add(MEM_OFFSET(), 32) } + // Used to simplify gas calculations for memory expansion. + // The cost to increase the memory to 4 MB is close to 30M gas function MAX_POSSIBLE_MEM() -> max { - max := 0x100000 // 1MB + max := 0x400000 // 4MB } function MAX_MEMORY_FRAME() -> max { @@ -3218,12 +3216,6 @@ object "EvmEmulator" { } } - function checkMemOverflow(location) { - if gt(location, MAX_MEMORY_FRAME()) { - panic() - } - } - function checkOverflow(data1, data2) { if lt(add(data1, data2), data2) { panic() diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 0a716511a..8ca655213 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -54,8 +54,10 @@ function MEM_OFFSET_INNER() -> offset { offset := add(MEM_OFFSET(), 32) } +// Used to simplify gas calculations for memory expansion. +// The cost to increase the memory to 4 MB is close to 30M gas function MAX_POSSIBLE_MEM() -> max { - max := 0x100000 // 1MB + max := 0x400000 // 4MB } function MAX_MEMORY_FRAME() -> max { @@ -121,12 +123,6 @@ function checkMemIsAccessible(index, offset) { } } -function checkMemOverflow(location) { - if gt(location, MAX_MEMORY_FRAME()) { - panic() - } -} - function checkOverflow(data1, data2) { if lt(add(data1, data2), data2) { panic() From 11176dcaa32cc35cf2276cfeaf9e3b5d90396c02 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sat, 26 Oct 2024 17:16:42 +0200 Subject: [PATCH 108/183] fix(EVM): Fix gas in EVM constructor (#1012) --- system-contracts/SystemContractsHashes.json | 4 +- .../contracts/ContractDeployer.sol | 62 +++++++++++-------- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 445827b74..c30b295a8 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": "0x01000697c616ad2f70268eedf874c28c7396a868e5a13f3b3401ed7693a9ec4d", - "sourceCodeHash": "0xa6ce082f01fa320322b961928086128e4f3dbd35928b8754f74e49c07c1db456" + "bytecodeHash": "0x01000741d061a22e8020f121a635ea94e9367c0492d7ea3f8a060ab5f47a8f8a", + "sourceCodeHash": "0x690a38ccd3230ff75453319bf415e57ee13805ad0342e9d7fc776ca41c18ac88" }, { "contractName": "Create2Factory", diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 5c8d6e129..63e0e8316 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -195,7 +195,25 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); - _evmDeployOnAddress(msg.sender, newAddress, _initCode); + _evmDeployOnAddress(uint32(gasleft()), msg.sender, 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 + function create2EVM( + bytes32 _salt, + bytes calldata _initCode + ) external payable override onlySystemCall returns (address) { + NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); + // 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(uint32(gasleft()), msg.sender, newAddress, _initCode); return newAddress; } @@ -231,25 +249,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address newAddress, bytes calldata _initCode ) external payable onlySystemCallFromEvmEmulator returns (address) { - _evmDeployOnAddress(msg.sender, 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 - function create2EVM( - bytes32 _salt, - bytes calldata _initCode - ) external payable override onlySystemCall returns (address) { - NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); - // 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(msg.sender, newAddress, _initCode); - + _evmDeployOnAddress(0, msg.sender, newAddress, _initCode); return newAddress; } @@ -410,7 +410,12 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _performDeployOnAddress(_bytecodeHash, _newAddress, _aaVersion, _input, true); } - function _evmDeployOnAddress(address _sender, address _newAddress, bytes calldata _initCode) internal { + function _evmDeployOnAddress( + uint32 _gasToPass, + address _sender, + address _newAddress, + bytes calldata _initCode + ) internal { if (_getAllowedBytecodeTypesMode() != AllowedBytecodeTypes.EraVmAndEVM) { revert EVMEmulationNotSupported(); } @@ -418,7 +423,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(_sender, _newAddress, AccountAbstractionVersion.None, _initCode); + _performDeployOnAddressEVM(_gasToPass, _sender, _newAddress, AccountAbstractionVersion.None, _initCode); } /// @notice Deploy a certain bytecode on the address. @@ -452,11 +457,13 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } /// @notice Deploy a certain bytecode on the address. + /// @param _gasToPass TODO /// @param _sender TODO /// @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( + uint32 _gasToPass, address _sender, address _newAddress, AccountAbstractionVersion _aaVersion, @@ -472,7 +479,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(_newAddress); // When constructing they just get the intrepeter bytecode hash in consutrcting mode - _constructEVMContract(_sender, _newAddress, _input); + _constructEVMContract(_gasToPass, _sender, _newAddress, _input); } /// @notice Check that bytecode hash is marked as known on the `KnownCodeStorage` system contracts @@ -544,7 +551,12 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { emit ContractDeployed(_sender, _bytecodeHash, _newAddress); } - function _constructEVMContract(address _sender, address _newAddress, bytes calldata _input) internal { + function _constructEVMContract( + uint32 gasToPass, + address _sender, + address _newAddress, + bytes calldata _input + ) internal { uint256 value = msg.value; // 1. Transfer the balance to the new address on the constructor call. if (value > 0) { @@ -566,7 +578,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } bytes memory paddedBytecode = EfficientCall.mimicCall({ - _gas: uint32(gasleft()), + _gas: gasToPass, // ergs, not EVM gas _address: _newAddress, _data: _input, _whoToMimic: _sender, From cc88802f6c74c6f43a34c6fdce5d2b99ceac1688 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sat, 26 Oct 2024 18:58:37 +0200 Subject: [PATCH 109/183] fix(EVM): Fix stipends (#1014) --- system-contracts/SystemContractsHashes.json | 36 +++++++++---------- system-contracts/contracts/Constants.sol | 2 ++ .../contracts/ContractDeployer.sol | 12 +++++-- system-contracts/contracts/EvmEmulator.yul | 30 +++++++++++----- .../EvmEmulatorFunctions.template.yul | 15 +++++--- 5 files changed, 63 insertions(+), 32 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index c30b295a8..0089f0a85 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": "0x010000774aa1c7c082646986a5c0b076334728bc55ca9a8f206cdcf2f7b9bbb5", + "bytecodeHash": "0x01000077fbba7c8f4a3afae79c335eefc97a06bf0960462a02d71620fa511b83", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f1aabdf55b55fdbbe0f255f75266faeb82d8f447d506918a994db2efcc", + "bytecodeHash": "0x010006f10387df0e25384b8e1647ad3d113d073ed9fbb028efcd97354d7265ff", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x01000047096f5dab39055215639242142c662792eda46d46f8a4a5994098e9d3", + "bytecodeHash": "0x01000047b2acbcfc30be1b0e33524acbb9c0546702fa055ab729ff148c5579d3", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013fc103b8e9c8823f0b5f607b54c3ced652b073481d7944b801d45b6136", + "bytecodeHash": "0x0100013f3655427cabae552ce6e029e1faa6bc47b62c24e91629e4ebd94513cd", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x01000741d061a22e8020f121a635ea94e9367c0492d7ea3f8a060ab5f47a8f8a", - "sourceCodeHash": "0x690a38ccd3230ff75453319bf415e57ee13805ad0342e9d7fc776ca41c18ac88" + "bytecodeHash": "0x010006995d45717ae05cb32bf83f20ac6afd3e830256b19e4b4848ffc049dab4", + "sourceCodeHash": "0xbbca34f18754b9910eab2def1363f1535b5b6833ad96f80b8f70d0f8676850e3" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003f22e7d580bc8e7543d921ac35aa24019162107a8c770a76e23df573a5", + "bytecodeHash": "0x0100003fe42e51e49f224a09d0e2fb7a6b89c5d9ca7a0c695b0a2df98ffecd08", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x01000509c4ed190e1d976223ef1d9d5e1441450b8c90c81ba9db7ac3143bd655", + "bytecodeHash": "0x010005099e763f853ae58bcecc5f35c0f4892ff38184472fa5649b64a0ed197e", "sourceCodeHash": "0x62e525189d13e7d59a88cfe834621bc7fb62cd38e2d830f9a1d1e056e229d2c8" }, { @@ -59,56 +59,56 @@ "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033bda7d60ad38b3df947d9143234528aa9c828212a60192d671341b993", + "bytecodeHash": "0x01000033f23e43c0c20fd5c0921314464e742a44f86c969f16a62a4e9f377af0", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000c11f196173983c4e73b40f008b8ff0f44ccee9af74ca53568b925abe4c", + "bytecodeHash": "0x010000c19a85edbe703789e796a6cddd924d426967d2d0b265637a273c3a68cb", "sourceCodeHash": "0xeb83e3a2ea2f50b93122363b8dd56fbcfe821d11723d849eecbde3d6af1147de" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000265037281ade86b965c995ebfee9b395e4bc8de5a4271fbf145d6186509", + "bytecodeHash": "0x010002655d4860b50d58dff8202c1262882feda90d04d80cca482111c62449a3", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f335bd082f4c62cbb2892f1d4942165dec7ef43bdf017e5f48a539a637", + "bytecodeHash": "0x010000f3c2c2afd410587562c39eb92a1a9db7a40620620d7a98c30f6fe38aa5", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x01000059f9bba78e1a9975df14c25faf992f0a68056a1d16976ba5e8cd36e3f5", + "bytecodeHash": "0x010000594fa01bdab3cd481702d2b0b15ee374d0cb49d11473b09e64a007d21c", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cfd7cf22490b8b82005cec551cba1a3de65ed34089ecfa338a795afd44", + "bytecodeHash": "0x010000cfb8bbb8324f7d2df3b077d93cf6ac410d1c5353f99f8a4038f2588c2a", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x0100004122b8a5696b8516afc2b2402428c27a088b7cba4a9e089637ad75cddc", + "bytecodeHash": "0x0100004112d30c5df65c36273ecd46356864e2194ad4b43afaeddb6adc66af8e", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c5ca32776369b696e34a5894d3b272c4f2a4f1ae04d0cb43d5da90adea", + "bytecodeHash": "0x010001c5a6801732584ea1804b91e5621ac25460be6b91196fc4d68fd3a65105", "sourceCodeHash": "0xc5ce25a94e3b510183635dd2fe0152dbcaa705bc8802fb3a4390253b5af3aa0a" }, { @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000d1d757b324579b300119cd16596a2a38dd855441a96332be81c741d08ea", - "sourceCodeHash": "0xefaa64a7e279961887feecbb6486964ecf1755ef5b9898881fb5fdcd04cd7419" + "bytecodeHash": "0x01000d2b8c3dcb96352ef62b5ad991df85a8089e1d3687b659d99ad06000e955", + "sourceCodeHash": "0x97db67755a652955b270810c869097ff0738d9065fdb67ddc54904ecffeb913d" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index 4fba3d615..310ea599e 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -163,3 +163,5 @@ uint256 constant BLOB_SIZE_BYTES = 126_976; /// @dev Max number of blobs currently supported uint256 constant MAX_NUMBER_OF_BLOBS = 6; + +uint32 constant EVM_GAS_STIPEND = 1 << 30; \ No newline at end of file diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 63e0e8316..7c5135c83 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; 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, SYSTEM_CONTEXT_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, SYSTEM_CONTEXT_CONTRACT, EVM_GAS_STIPEND} from "./Constants.sol"; import {Utils} from "./libraries/Utils.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; @@ -249,7 +249,15 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address newAddress, bytes calldata _initCode ) external payable onlySystemCallFromEvmEmulator returns (address) { - _evmDeployOnAddress(0, msg.sender, newAddress, _initCode); + uint32 providedErgs; + uint32 stipend = EVM_GAS_STIPEND; + assembly { + let _gas := gas() + if gt(_gas, stipend) { + providedErgs := sub(_gas, stipend) + } + } + _evmDeployOnAddress(providedErgs, msg.sender, newAddress, _initCode); return newAddress; } diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 9c4377428..82cb13ca3 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -175,6 +175,13 @@ object "EvmEmulator" { gasRemaining := sub(prevGas, toCharge) } + function providedErgs() -> ergs { + let _gas := gas() + if gt(_gas, EVM_GAS_STIPEND()) { + ergs := sub(_gas, EVM_GAS_STIPEND()) + } + } + function checkMemIsAccessible(index, offset) { checkOverflow(index, offset) @@ -798,7 +805,7 @@ object "EvmEmulator" { _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( - 0, // 0 gas since VM will add EVM_GAS_STIPEND() to gas + providedErgs(), addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, @@ -832,8 +839,8 @@ object "EvmEmulator" { _pushEVMFrame(gasToPass, false) // VM will add EVM_GAS_STIPEND() to gas for this call // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract - // so we need to pass some gas for MsgValueSimulator - success := call(MSG_VALUE_SIMULATOR_STIPEND_GAS(), addr, value, argsOffset, argsSize, 0, 0) + // so we need to add some gas for MsgValueSimulator + success := call(add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), providedErgs()), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } @@ -854,7 +861,7 @@ object "EvmEmulator" { } default { _pushEVMFrame(gasToPass, true) - success := staticcall(0, addr, argsOffset, argsSize, 0, 0) // 0 gas since VM will add EVM_GAS_STIPEND() to gas + success := staticcall(providedErgs(), addr, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } @@ -3208,6 +3215,13 @@ object "EvmEmulator" { gasRemaining := sub(prevGas, toCharge) } + function providedErgs() -> ergs { + let _gas := gas() + if gt(_gas, EVM_GAS_STIPEND()) { + ergs := sub(_gas, EVM_GAS_STIPEND()) + } + } + function checkMemIsAccessible(index, offset) { checkOverflow(index, offset) @@ -3831,7 +3845,7 @@ object "EvmEmulator" { _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( - 0, // 0 gas since VM will add EVM_GAS_STIPEND() to gas + providedErgs(), addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, @@ -3865,8 +3879,8 @@ object "EvmEmulator" { _pushEVMFrame(gasToPass, false) // VM will add EVM_GAS_STIPEND() to gas for this call // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract - // so we need to pass some gas for MsgValueSimulator - success := call(MSG_VALUE_SIMULATOR_STIPEND_GAS(), addr, value, argsOffset, argsSize, 0, 0) + // so we need to add some gas for MsgValueSimulator + success := call(add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), providedErgs()), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } @@ -3887,7 +3901,7 @@ object "EvmEmulator" { } default { _pushEVMFrame(gasToPass, true) - success := staticcall(0, addr, argsOffset, argsSize, 0, 0) // 0 gas since VM will add EVM_GAS_STIPEND() to gas + success := staticcall(providedErgs(), addr, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 8ca655213..db876f7ea 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -115,6 +115,13 @@ function chargeGas(prevGas, toCharge) -> gasRemaining { gasRemaining := sub(prevGas, toCharge) } +function providedErgs() -> ergs { + let _gas := gas() + if gt(_gas, EVM_GAS_STIPEND()) { + ergs := sub(_gas, EVM_GAS_STIPEND()) + } +} + function checkMemIsAccessible(index, offset) { checkOverflow(index, offset) @@ -738,7 +745,7 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEv _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( - 0, // 0 gas since VM will add EVM_GAS_STIPEND() to gas + providedErgs(), addr, add(MEM_OFFSET_INNER(), argsOffset), argsSize, @@ -772,8 +779,8 @@ function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, r _pushEVMFrame(gasToPass, false) // VM will add EVM_GAS_STIPEND() to gas for this call // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract - // so we need to pass some gas for MsgValueSimulator - success := call(MSG_VALUE_SIMULATOR_STIPEND_GAS(), addr, value, argsOffset, argsSize, 0, 0) + // so we need to add some gas for MsgValueSimulator + success := call(add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), providedErgs()), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } @@ -794,7 +801,7 @@ function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, re } default { _pushEVMFrame(gasToPass, true) - success := staticcall(0, addr, argsOffset, argsSize, 0, 0) // 0 gas since VM will add EVM_GAS_STIPEND() to gas + success := staticcall(providedErgs(), addr, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } From 9135b563a252ac7279ff95d8e22aa670fb41c69b Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sat, 26 Oct 2024 20:15:32 +0200 Subject: [PATCH 110/183] fix(EVM): Cache fixed context values (#1015) --- system-contracts/contracts/EvmEmulator.yul | 200 +++++++++++++++--- system-contracts/contracts/SystemContext.sol | 1 + .../EvmEmulatorFunctions.template.yul | 43 +++- .../evm-emulator/EvmEmulatorLoop.template.yul | 57 +++-- 4 files changed, 262 insertions(+), 39 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 82cb13ca3..e21b5f874 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -86,8 +86,44 @@ object "EvmEmulator" { addr := 0x0000000000000000000000000000000000008009 } + function ORIGIN_CACHE_OFFSET() -> offset { + offset := mul(23, 32) + } + + function GASPRICE_CACHE_OFFSET() -> offset { + offset := mul(24, 32) + } + + function COINBASE_CACHE_OFFSET() -> offset { + offset := mul(25, 32) + } + + function BLOCKTIMESTAMP_CACHE_OFFSET() -> offset { + offset := mul(26, 32) + } + + function BLOCKNUMBER_CACHE_OFFSET() -> offset { + offset := mul(27, 32) + } + + function PREVRANDAO_CACHE_OFFSET() -> offset { + offset := mul(28, 32) + } + + function GASLIMIT_CACHE_OFFSET() -> offset { + offset := mul(29, 32) + } + + function CHAINID_CACHE_OFFSET() -> offset { + offset := mul(30, 32) + } + + function BASEFEE_CACHE_OFFSET() -> offset { + offset := mul(31, 32) + } + function LAST_RETURNDATA_SIZE_OFFSET() -> offset { - offset := mul(32, 32) + offset := add(BASEFEE_CACHE_OFFSET(), 32) } function STACK_OFFSET() -> offset { @@ -167,6 +203,11 @@ object "EvmEmulator" { revert(0, 32) } + function cached(cacheIndex, value) -> _value { + _value := value + mstore(cacheIndex, _value) + } + function chargeGas(prevGas, toCharge) -> gasRemaining { if lt(prevGas, toCharge) { panic() @@ -1599,7 +1640,6 @@ object "EvmEmulator" { } case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, address(), stackHead) ip := add(ip, 1) } @@ -1619,8 +1659,11 @@ object "EvmEmulator" { } case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - - sp, stackHead := pushStackItem(sp, origin(), stackHead) + let _origin := mload(ORIGIN_CACHE_OFFSET()) + if iszero(_origin) { + _origin := cached(ORIGIN_CACHE_OFFSET(), origin()) + } + sp, stackHead := pushStackItem(sp, _origin, stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER @@ -1708,8 +1751,11 @@ object "EvmEmulator" { } case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - - sp, stackHead := pushStackItem(sp, gasprice(), stackHead) + let _gasprice := mload(GASPRICE_CACHE_OFFSET()) + if iszero(_gasprice) { + _gasprice := cached(GASPRICE_CACHE_OFFSET(), gasprice()) + } + sp, stackHead := pushStackItem(sp, _gasprice, stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE @@ -1821,32 +1867,56 @@ object "EvmEmulator" { } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, coinbase(), stackHead) + let _coinbase := mload(COINBASE_CACHE_OFFSET()) + if iszero(_coinbase) { + _coinbase := cached(COINBASE_CACHE_OFFSET(), coinbase()) + } + sp, stackHead := pushStackItem(sp, _coinbase, stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, timestamp(), stackHead) + let _blocktimestamp := mload(BLOCKTIMESTAMP_CACHE_OFFSET()) + if iszero(_blocktimestamp) { + _blocktimestamp := cached(BLOCKTIMESTAMP_CACHE_OFFSET(), timestamp()) + } + sp, stackHead := pushStackItem(sp, _blocktimestamp, stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, number(), stackHead) + let _blocknumber := mload(BLOCKNUMBER_CACHE_OFFSET()) + if iszero(_blocknumber) { + _blocknumber := cached(BLOCKNUMBER_CACHE_OFFSET(), number()) + } + sp, stackHead := pushStackItem(sp, _blocknumber, stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, prevrandao(), stackHead) + let _prevrandao := mload(PREVRANDAO_CACHE_OFFSET()) + if iszero(_prevrandao) { + _prevrandao := cached(PREVRANDAO_CACHE_OFFSET(), prevrandao()) + } + sp, stackHead := pushStackItem(sp, _prevrandao, stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, gaslimit(), stackHead) + let _gasLimit := mload(GASLIMIT_CACHE_OFFSET()) + if iszero(_gasLimit) { + _gasLimit := cached(GASLIMIT_CACHE_OFFSET(), gaslimit()) + } + sp, stackHead := pushStackItem(sp, _gasLimit, stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, chainid(), stackHead) + let _chainId := mload(CHAINID_CACHE_OFFSET()) + if iszero(_chainId) { + _chainId := cached(CHAINID_CACHE_OFFSET(), chainid()) + } + sp, stackHead := pushStackItem(sp, _chainId, stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE @@ -1856,7 +1926,11 @@ object "EvmEmulator" { } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, basefee(), stackHead) + let _baseFee := mload(BASEFEE_CACHE_OFFSET()) + if iszero(_baseFee) { + _baseFee := cached(BASEFEE_CACHE_OFFSET(), basefee()) + } + sp, stackHead := pushStackItem(sp, _baseFee, stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP @@ -3126,8 +3200,44 @@ object "EvmEmulator" { addr := 0x0000000000000000000000000000000000008009 } + function ORIGIN_CACHE_OFFSET() -> offset { + offset := mul(23, 32) + } + + function GASPRICE_CACHE_OFFSET() -> offset { + offset := mul(24, 32) + } + + function COINBASE_CACHE_OFFSET() -> offset { + offset := mul(25, 32) + } + + function BLOCKTIMESTAMP_CACHE_OFFSET() -> offset { + offset := mul(26, 32) + } + + function BLOCKNUMBER_CACHE_OFFSET() -> offset { + offset := mul(27, 32) + } + + function PREVRANDAO_CACHE_OFFSET() -> offset { + offset := mul(28, 32) + } + + function GASLIMIT_CACHE_OFFSET() -> offset { + offset := mul(29, 32) + } + + function CHAINID_CACHE_OFFSET() -> offset { + offset := mul(30, 32) + } + + function BASEFEE_CACHE_OFFSET() -> offset { + offset := mul(31, 32) + } + function LAST_RETURNDATA_SIZE_OFFSET() -> offset { - offset := mul(32, 32) + offset := add(BASEFEE_CACHE_OFFSET(), 32) } function STACK_OFFSET() -> offset { @@ -3207,6 +3317,11 @@ object "EvmEmulator" { revert(0, 32) } + function cached(cacheIndex, value) -> _value { + _value := value + mstore(cacheIndex, _value) + } + function chargeGas(prevGas, toCharge) -> gasRemaining { if lt(prevGas, toCharge) { panic() @@ -4639,7 +4754,6 @@ object "EvmEmulator" { } case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, address(), stackHead) ip := add(ip, 1) } @@ -4659,8 +4773,11 @@ object "EvmEmulator" { } case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - - sp, stackHead := pushStackItem(sp, origin(), stackHead) + let _origin := mload(ORIGIN_CACHE_OFFSET()) + if iszero(_origin) { + _origin := cached(ORIGIN_CACHE_OFFSET(), origin()) + } + sp, stackHead := pushStackItem(sp, _origin, stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER @@ -4748,8 +4865,11 @@ object "EvmEmulator" { } case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - - sp, stackHead := pushStackItem(sp, gasprice(), stackHead) + let _gasprice := mload(GASPRICE_CACHE_OFFSET()) + if iszero(_gasprice) { + _gasprice := cached(GASPRICE_CACHE_OFFSET(), gasprice()) + } + sp, stackHead := pushStackItem(sp, _gasprice, stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE @@ -4861,32 +4981,56 @@ object "EvmEmulator" { } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, coinbase(), stackHead) + let _coinbase := mload(COINBASE_CACHE_OFFSET()) + if iszero(_coinbase) { + _coinbase := cached(COINBASE_CACHE_OFFSET(), coinbase()) + } + sp, stackHead := pushStackItem(sp, _coinbase, stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, timestamp(), stackHead) + let _blocktimestamp := mload(BLOCKTIMESTAMP_CACHE_OFFSET()) + if iszero(_blocktimestamp) { + _blocktimestamp := cached(BLOCKTIMESTAMP_CACHE_OFFSET(), timestamp()) + } + sp, stackHead := pushStackItem(sp, _blocktimestamp, stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, number(), stackHead) + let _blocknumber := mload(BLOCKNUMBER_CACHE_OFFSET()) + if iszero(_blocknumber) { + _blocknumber := cached(BLOCKNUMBER_CACHE_OFFSET(), number()) + } + sp, stackHead := pushStackItem(sp, _blocknumber, stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, prevrandao(), stackHead) + let _prevrandao := mload(PREVRANDAO_CACHE_OFFSET()) + if iszero(_prevrandao) { + _prevrandao := cached(PREVRANDAO_CACHE_OFFSET(), prevrandao()) + } + sp, stackHead := pushStackItem(sp, _prevrandao, stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, gaslimit(), stackHead) + let _gasLimit := mload(GASLIMIT_CACHE_OFFSET()) + if iszero(_gasLimit) { + _gasLimit := cached(GASLIMIT_CACHE_OFFSET(), gaslimit()) + } + sp, stackHead := pushStackItem(sp, _gasLimit, stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, chainid(), stackHead) + let _chainId := mload(CHAINID_CACHE_OFFSET()) + if iszero(_chainId) { + _chainId := cached(CHAINID_CACHE_OFFSET(), chainid()) + } + sp, stackHead := pushStackItem(sp, _chainId, stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE @@ -4896,7 +5040,11 @@ object "EvmEmulator" { } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, basefee(), stackHead) + let _baseFee := mload(BASEFEE_CACHE_OFFSET()) + if iszero(_baseFee) { + _baseFee := cached(BASEFEE_CACHE_OFFSET(), basefee()) + } + sp, stackHead := pushStackItem(sp, _baseFee, stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP diff --git a/system-contracts/contracts/SystemContext.sol b/system-contracts/contracts/SystemContext.sol index eab089e8f..10eef6901 100644 --- a/system-contracts/contracts/SystemContext.sol +++ b/system-contracts/contracts/SystemContext.sol @@ -42,6 +42,7 @@ contract SystemContext is ISystemContext, ISystemContextDeprecated, SystemContra /// @notice The `block.coinbase` in the current transaction. /// @dev For the support of coinbase, we will use the bootloader formal address for now + /// @dev (!) EVM emulator doesn't expect this value to change address public coinbase = BOOTLOADER_FORMAL_ADDRESS; /// @notice Formal `block.difficulty` parameter. diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index db876f7ea..ef48139f5 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -26,8 +26,44 @@ function MSG_VALUE_SYSTEM_CONTRACT() -> addr { addr := 0x0000000000000000000000000000000000008009 } +function ORIGIN_CACHE_OFFSET() -> offset { + offset := mul(23, 32) +} + +function GASPRICE_CACHE_OFFSET() -> offset { + offset := mul(24, 32) +} + +function COINBASE_CACHE_OFFSET() -> offset { + offset := mul(25, 32) +} + +function BLOCKTIMESTAMP_CACHE_OFFSET() -> offset { + offset := mul(26, 32) +} + +function BLOCKNUMBER_CACHE_OFFSET() -> offset { + offset := mul(27, 32) +} + +function PREVRANDAO_CACHE_OFFSET() -> offset { + offset := mul(28, 32) +} + +function GASLIMIT_CACHE_OFFSET() -> offset { + offset := mul(29, 32) +} + +function CHAINID_CACHE_OFFSET() -> offset { + offset := mul(30, 32) +} + +function BASEFEE_CACHE_OFFSET() -> offset { + offset := mul(31, 32) +} + function LAST_RETURNDATA_SIZE_OFFSET() -> offset { - offset := mul(32, 32) + offset := add(BASEFEE_CACHE_OFFSET(), 32) } function STACK_OFFSET() -> offset { @@ -107,6 +143,11 @@ function panic() { revert(0, 32) } +function cached(cacheIndex, value) -> _value { + _value := value + mstore(cacheIndex, _value) +} + function chargeGas(prevGas, toCharge) -> gasRemaining { if lt(prevGas, toCharge) { panic() diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index c3bd57186..52d04d072 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -299,7 +299,6 @@ for { } true { } { } case 0x30 { // OP_ADDRESS evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, address(), stackHead) ip := add(ip, 1) } @@ -319,8 +318,11 @@ for { } true { } { } case 0x32 { // OP_ORIGIN evmGasLeft := chargeGas(evmGasLeft, 2) - - sp, stackHead := pushStackItem(sp, origin(), stackHead) + let _origin := mload(ORIGIN_CACHE_OFFSET()) + if iszero(_origin) { + _origin := cached(ORIGIN_CACHE_OFFSET(), origin()) + } + sp, stackHead := pushStackItem(sp, _origin, stackHead) ip := add(ip, 1) } case 0x33 { // OP_CALLER @@ -408,8 +410,11 @@ for { } true { } { } case 0x3A { // OP_GASPRICE evmGasLeft := chargeGas(evmGasLeft, 2) - - sp, stackHead := pushStackItem(sp, gasprice(), stackHead) + let _gasprice := mload(GASPRICE_CACHE_OFFSET()) + if iszero(_gasprice) { + _gasprice := cached(GASPRICE_CACHE_OFFSET(), gasprice()) + } + sp, stackHead := pushStackItem(sp, _gasprice, stackHead) ip := add(ip, 1) } case 0x3B { // OP_EXTCODESIZE @@ -521,32 +526,56 @@ for { } true { } { } case 0x41 { // OP_COINBASE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, coinbase(), stackHead) + let _coinbase := mload(COINBASE_CACHE_OFFSET()) + if iszero(_coinbase) { + _coinbase := cached(COINBASE_CACHE_OFFSET(), coinbase()) + } + sp, stackHead := pushStackItem(sp, _coinbase, stackHead) ip := add(ip, 1) } case 0x42 { // OP_TIMESTAMP evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, timestamp(), stackHead) + let _blocktimestamp := mload(BLOCKTIMESTAMP_CACHE_OFFSET()) + if iszero(_blocktimestamp) { + _blocktimestamp := cached(BLOCKTIMESTAMP_CACHE_OFFSET(), timestamp()) + } + sp, stackHead := pushStackItem(sp, _blocktimestamp, stackHead) ip := add(ip, 1) } case 0x43 { // OP_NUMBER evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, number(), stackHead) + let _blocknumber := mload(BLOCKNUMBER_CACHE_OFFSET()) + if iszero(_blocknumber) { + _blocknumber := cached(BLOCKNUMBER_CACHE_OFFSET(), number()) + } + sp, stackHead := pushStackItem(sp, _blocknumber, stackHead) ip := add(ip, 1) } case 0x44 { // OP_PREVRANDAO evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, prevrandao(), stackHead) + let _prevrandao := mload(PREVRANDAO_CACHE_OFFSET()) + if iszero(_prevrandao) { + _prevrandao := cached(PREVRANDAO_CACHE_OFFSET(), prevrandao()) + } + sp, stackHead := pushStackItem(sp, _prevrandao, stackHead) ip := add(ip, 1) } case 0x45 { // OP_GASLIMIT evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, gaslimit(), stackHead) + let _gasLimit := mload(GASLIMIT_CACHE_OFFSET()) + if iszero(_gasLimit) { + _gasLimit := cached(GASLIMIT_CACHE_OFFSET(), gaslimit()) + } + sp, stackHead := pushStackItem(sp, _gasLimit, stackHead) ip := add(ip, 1) } case 0x46 { // OP_CHAINID evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, chainid(), stackHead) + let _chainId := mload(CHAINID_CACHE_OFFSET()) + if iszero(_chainId) { + _chainId := cached(CHAINID_CACHE_OFFSET(), chainid()) + } + sp, stackHead := pushStackItem(sp, _chainId, stackHead) ip := add(ip, 1) } case 0x47 { // OP_SELFBALANCE @@ -556,7 +585,11 @@ for { } true { } { } case 0x48 { // OP_BASEFEE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, basefee(), stackHead) + let _baseFee := mload(BASEFEE_CACHE_OFFSET()) + if iszero(_baseFee) { + _baseFee := cached(BASEFEE_CACHE_OFFSET(), basefee()) + } + sp, stackHead := pushStackItem(sp, _baseFee, stackHead) ip := add(ip, 1) } case 0x50 { // OP_POP From b50f3617b685bfedd2bd0ca46b44cd4e16221895 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sat, 26 Oct 2024 22:42:23 +0200 Subject: [PATCH 111/183] Fix(EVM): Not revert caller frame in CREATE if balance insufficient (#1018) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 254 +++++++++--------- .../EvmEmulatorFunctions.template.yul | 127 +++++---- 3 files changed, 188 insertions(+), 197 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 0089f0a85..4adbab2d1 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000d2b8c3dcb96352ef62b5ad991df85a8089e1d3687b659d99ad06000e955", - "sourceCodeHash": "0x97db67755a652955b270810c869097ff0738d9065fdb67ddc54904ecffeb913d" + "bytecodeHash": "0x01000d1da56c97d7554e0e9c8397a970b5a44c569aab6fb6661f820c5ae3e58e", + "sourceCodeHash": "0xb6b321ccc368ca848ca6675eaf968dedd4b4da388d74829cd3fb9927f4550071" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index e21b5f874..61aa34fed 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1116,52 +1116,25 @@ object "EvmEmulator" { // CREATE FUNCTIONALITY //////////////////////////////////////////////////////////////// - function performSystemCallForCreate( - value, - bytecodeStart, - bytecodeLen, - ) -> success { - let farCallAbi := shl(248, 1) // system call - // dataOffset is 0 - farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) - farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) - farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow - // shardId is 0 - // forwardingMode is 0 - // not constructor call (ContractDeployer will call constructor) - - switch iszero(value) - case 0 { - success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, DEPLOYER_SYSTEM_CONTRACT(), 1, 0) - } - default { - success := verbatim_6i_1o("system_call", DEPLOYER_SYSTEM_CONTRACT(), farCallAbi, 0, 0, 0, 0) - } - } - - function incrementDeploymentNonce() -> nonce { - // function incrementDeploymentNonce(address _address) - mstore(0, 0x306395c600000000000000000000000000000000000000000000000000000000) - mstore(4, address()) + function performCreate(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { + let value, offset, size - performSystemCall(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) + popStackCheck(oldSp, 3) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - returndatacopy(0, 0, 32) - nonce := mload(0) + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, false, 0) } - function _fetchConstructorReturnGas() -> gasLeft { - mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - - let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) + function performCreate2(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { + let value, offset, size, salt - if iszero(success) { - // This error should never happen - revert(0, 0) - } + popStackCheck(oldSp, 4) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, salt := popStackItemWithoutCheck(sp, stackHead) - returndatacopy(0, 0, 32) - gasLeft := mload(0) + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, true, salt) } function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { @@ -1190,13 +1163,21 @@ object "EvmEmulator" { _eraseReturndataPointer() - offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow - - let gasForTheCall := capGasForCall(evmGasLeft, INF_PASS_GAS()) + let err := 0 + if value { + if gt(value, selfbalance()) { + err := 1 + } + } - if gt(value, selfbalance()) { // it should be checked before actual deploy call - revertWithGas(evmGasLeft) // gasForTheCall not consumed + if iszero(err) { + offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow + evmGasLeft, addr := _executeCreate(offset, size, value, evmGasLeft, isCreate2, salt) } + } + + function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { + let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) let bytecodeHash := 0 if isCreate2 { @@ -1204,8 +1185,7 @@ object "EvmEmulator" { } // we want to calculate the address of new contract, and if it is deployable (no collision), - // we need to increment deploy nonce. Otherwise - panic. - // We should revert with gas if nonce overflowed, but this should not happen in reality anyway + // we need to increment deploy nonce. // selector: function precreateEvmAccountFromEmulator(bytes32 salt, bytes32 evmBytecodeHash) mstore(0, 0xf81dae8600000000000000000000000000000000000000000000000000000000) @@ -1214,9 +1194,10 @@ object "EvmEmulator" { let precreateResult := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) if iszero(precreateResult) { - // collision, nonce overflow or EVM not allowed - // this is *internal* panic, consuming all passed gas - evmGasLeft := chargeGas(evmGasLeft, gasForTheCall) + // Collision, nonce overflow or EVM not allowed. + // This is *internal* panic, consuming all passed gas. + // Note: we should not consume all gas if nonce overflowed, but this should not happen in reality anyway + evmGasLeft := chargeGas(evmGasLeftOld, gasForTheCall) } if precreateResult { @@ -1262,29 +1243,45 @@ object "EvmEmulator" { } let gasUsed := sub(gasForTheCall, gasLeft) - evmGasLeft := chargeGas(evmGasLeft, gasUsed) + evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) } } - function performCreate(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { - let value, offset, size - - popStackCheck(oldSp, 3) - value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - offset, sp, size := popStackItemWithoutCheck(sp, stackHead) + function performSystemCallForCreate( + value, + bytecodeStart, + bytecodeLen, + ) -> success { + let farCallAbi := shl(248, 1) // system call + // dataOffset is 0 + farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) + farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) + farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + // shardId is 0 + // forwardingMode is 0 + // not constructor call (ContractDeployer will call constructor) - evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, false, 0) + switch iszero(value) + case 0 { + success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, DEPLOYER_SYSTEM_CONTRACT(), 1, 0) + } + default { + success := verbatim_6i_1o("system_call", DEPLOYER_SYSTEM_CONTRACT(), farCallAbi, 0, 0, 0, 0) + } } - function performCreate2(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { - let value, offset, size, salt + function _fetchConstructorReturnGas() -> gasLeft { + mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - popStackCheck(oldSp, 4) - value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, salt := popStackItemWithoutCheck(sp, stackHead) + let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) - evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, true, salt) + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + returndatacopy(0, 0, 32) + gasLeft := mload(0) } //////////////////////////////////////////////////////////////// @@ -4230,52 +4227,25 @@ object "EvmEmulator" { // CREATE FUNCTIONALITY //////////////////////////////////////////////////////////////// - function performSystemCallForCreate( - value, - bytecodeStart, - bytecodeLen, - ) -> success { - let farCallAbi := shl(248, 1) // system call - // dataOffset is 0 - farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) - farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) - farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow - // shardId is 0 - // forwardingMode is 0 - // not constructor call (ContractDeployer will call constructor) - - switch iszero(value) - case 0 { - success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, DEPLOYER_SYSTEM_CONTRACT(), 1, 0) - } - default { - success := verbatim_6i_1o("system_call", DEPLOYER_SYSTEM_CONTRACT(), farCallAbi, 0, 0, 0, 0) - } - } - - function incrementDeploymentNonce() -> nonce { - // function incrementDeploymentNonce(address _address) - mstore(0, 0x306395c600000000000000000000000000000000000000000000000000000000) - mstore(4, address()) + function performCreate(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { + let value, offset, size - performSystemCall(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) + popStackCheck(oldSp, 3) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - returndatacopy(0, 0, 32) - nonce := mload(0) + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, false, 0) } - function _fetchConstructorReturnGas() -> gasLeft { - mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - - let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) + function performCreate2(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { + let value, offset, size, salt - if iszero(success) { - // This error should never happen - revert(0, 0) - } + popStackCheck(oldSp, 4) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, salt := popStackItemWithoutCheck(sp, stackHead) - returndatacopy(0, 0, 32) - gasLeft := mload(0) + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, true, salt) } function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { @@ -4304,13 +4274,21 @@ object "EvmEmulator" { _eraseReturndataPointer() - offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow - - let gasForTheCall := capGasForCall(evmGasLeft, INF_PASS_GAS()) + let err := 0 + if value { + if gt(value, selfbalance()) { + err := 1 + } + } - if gt(value, selfbalance()) { // it should be checked before actual deploy call - revertWithGas(evmGasLeft) // gasForTheCall not consumed + if iszero(err) { + offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow + evmGasLeft, addr := _executeCreate(offset, size, value, evmGasLeft, isCreate2, salt) } + } + + function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { + let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) let bytecodeHash := 0 if isCreate2 { @@ -4318,8 +4296,7 @@ object "EvmEmulator" { } // we want to calculate the address of new contract, and if it is deployable (no collision), - // we need to increment deploy nonce. Otherwise - panic. - // We should revert with gas if nonce overflowed, but this should not happen in reality anyway + // we need to increment deploy nonce. // selector: function precreateEvmAccountFromEmulator(bytes32 salt, bytes32 evmBytecodeHash) mstore(0, 0xf81dae8600000000000000000000000000000000000000000000000000000000) @@ -4328,9 +4305,10 @@ object "EvmEmulator" { let precreateResult := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) if iszero(precreateResult) { - // collision, nonce overflow or EVM not allowed - // this is *internal* panic, consuming all passed gas - evmGasLeft := chargeGas(evmGasLeft, gasForTheCall) + // Collision, nonce overflow or EVM not allowed. + // This is *internal* panic, consuming all passed gas. + // Note: we should not consume all gas if nonce overflowed, but this should not happen in reality anyway + evmGasLeft := chargeGas(evmGasLeftOld, gasForTheCall) } if precreateResult { @@ -4376,29 +4354,45 @@ object "EvmEmulator" { } let gasUsed := sub(gasForTheCall, gasLeft) - evmGasLeft := chargeGas(evmGasLeft, gasUsed) + evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) } } - function performCreate(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { - let value, offset, size - - popStackCheck(oldSp, 3) - value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - offset, sp, size := popStackItemWithoutCheck(sp, stackHead) + function performSystemCallForCreate( + value, + bytecodeStart, + bytecodeLen, + ) -> success { + let farCallAbi := shl(248, 1) // system call + // dataOffset is 0 + farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) + farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) + farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + // shardId is 0 + // forwardingMode is 0 + // not constructor call (ContractDeployer will call constructor) - evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, false, 0) + switch iszero(value) + case 0 { + success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, DEPLOYER_SYSTEM_CONTRACT(), 1, 0) + } + default { + success := verbatim_6i_1o("system_call", DEPLOYER_SYSTEM_CONTRACT(), farCallAbi, 0, 0, 0, 0) + } } - function performCreate2(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { - let value, offset, size, salt + function _fetchConstructorReturnGas() -> gasLeft { + mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - popStackCheck(oldSp, 4) - value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, salt := popStackItemWithoutCheck(sp, stackHead) + let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) - evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, true, salt) + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + returndatacopy(0, 0, 32) + gasLeft := mload(0) } //////////////////////////////////////////////////////////////// diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index ef48139f5..2d628d0f9 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -1056,52 +1056,25 @@ function _eraseReturndataPointer() { // CREATE FUNCTIONALITY //////////////////////////////////////////////////////////////// -function performSystemCallForCreate( - value, - bytecodeStart, - bytecodeLen, -) -> success { - let farCallAbi := shl(248, 1) // system call - // dataOffset is 0 - farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) - farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) - farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow - // shardId is 0 - // forwardingMode is 0 - // not constructor call (ContractDeployer will call constructor) - - switch iszero(value) - case 0 { - success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, DEPLOYER_SYSTEM_CONTRACT(), 1, 0) - } - default { - success := verbatim_6i_1o("system_call", DEPLOYER_SYSTEM_CONTRACT(), farCallAbi, 0, 0, 0, 0) - } -} - -function incrementDeploymentNonce() -> nonce { - // function incrementDeploymentNonce(address _address) - mstore(0, 0x306395c600000000000000000000000000000000000000000000000000000000) - mstore(4, address()) +function performCreate(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { + let value, offset, size - performSystemCall(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) + popStackCheck(oldSp, 3) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, size := popStackItemWithoutCheck(sp, stackHead) - returndatacopy(0, 0, 32) - nonce := mload(0) + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, false, 0) } -function _fetchConstructorReturnGas() -> gasLeft { - mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - - let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) +function performCreate2(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { + let value, offset, size, salt - if iszero(success) { - // This error should never happen - revert(0, 0) - } + popStackCheck(oldSp, 4) + value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) + offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + size, sp, salt := popStackItemWithoutCheck(sp, stackHead) - returndatacopy(0, 0, 32) - gasLeft := mload(0) + evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, true, salt) } function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { @@ -1130,13 +1103,21 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, _eraseReturndataPointer() - offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow - - let gasForTheCall := capGasForCall(evmGasLeft, INF_PASS_GAS()) + let err := 0 + if value { + if gt(value, selfbalance()) { + err := 1 + } + } - if gt(value, selfbalance()) { // it should be checked before actual deploy call - revertWithGas(evmGasLeft) // gasForTheCall not consumed + if iszero(err) { + offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow + evmGasLeft, addr := _executeCreate(offset, size, value, evmGasLeft, isCreate2, salt) } +} + +function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { + let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) let bytecodeHash := 0 if isCreate2 { @@ -1144,8 +1125,7 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, } // we want to calculate the address of new contract, and if it is deployable (no collision), - // we need to increment deploy nonce. Otherwise - panic. - // We should revert with gas if nonce overflowed, but this should not happen in reality anyway + // we need to increment deploy nonce. // selector: function precreateEvmAccountFromEmulator(bytes32 salt, bytes32 evmBytecodeHash) mstore(0, 0xf81dae8600000000000000000000000000000000000000000000000000000000) @@ -1154,9 +1134,10 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, let precreateResult := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) if iszero(precreateResult) { - // collision, nonce overflow or EVM not allowed - // this is *internal* panic, consuming all passed gas - evmGasLeft := chargeGas(evmGasLeft, gasForTheCall) + // Collision, nonce overflow or EVM not allowed. + // This is *internal* panic, consuming all passed gas. + // Note: we should not consume all gas if nonce overflowed, but this should not happen in reality anyway + evmGasLeft := chargeGas(evmGasLeftOld, gasForTheCall) } if precreateResult { @@ -1202,29 +1183,45 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, } let gasUsed := sub(gasForTheCall, gasLeft) - evmGasLeft := chargeGas(evmGasLeft, gasUsed) + evmGasLeft := chargeGas(evmGasLeftOld, gasUsed) } } -function performCreate(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { - let value, offset, size - - popStackCheck(oldSp, 3) - value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - offset, sp, size := popStackItemWithoutCheck(sp, stackHead) +function performSystemCallForCreate( + value, + bytecodeStart, + bytecodeLen, +) -> success { + let farCallAbi := shl(248, 1) // system call + // dataOffset is 0 + farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) + farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) + farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + // shardId is 0 + // forwardingMode is 0 + // not constructor call (ContractDeployer will call constructor) - evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, false, 0) + switch iszero(value) + case 0 { + success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, DEPLOYER_SYSTEM_CONTRACT(), 1, 0) + } + default { + success := verbatim_6i_1o("system_call", DEPLOYER_SYSTEM_CONTRACT(), farCallAbi, 0, 0, 0, 0) + } } -function performCreate2(oldEvmGasLeft, oldSp, oldStackHead) -> evmGasLeft, sp, stackHead { - let value, offset, size, salt +function _fetchConstructorReturnGas() -> gasLeft { + mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - popStackCheck(oldSp, 4) - value, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, salt := popStackItemWithoutCheck(sp, stackHead) + let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) - evmGasLeft, stackHead := $llvm_NoInline_llvm$_genericCreate(offset, size, value, oldEvmGasLeft, true, salt) + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + returndatacopy(0, 0, 32) + gasLeft := mload(0) } //////////////////////////////////////////////////////////////// From e0fb26d1f6e19821669172461702edd555c07e99 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sat, 26 Oct 2024 23:23:18 +0200 Subject: [PATCH 112/183] fix(EVM): Fix stipend for transfers (#1019) --- system-contracts/contracts/EvmEmulator.yul | 116 +++++++----------- .../EvmEmulatorFunctions.template.yul | 58 ++++----- 2 files changed, 66 insertions(+), 108 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 61aa34fed..19a8d41a6 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -686,7 +686,7 @@ object "EvmEmulator" { // 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, 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. // 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. let gasUsed := 100 // warm address access cost @@ -694,28 +694,28 @@ object "EvmEmulator" { gasUsed := 2600 // cold address access cost } + // memory_expansion_cost + gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + if gt(value, 0) { - gasUsed := add(gasUsed, 6700) // positive_value_cost - stipend - gasToPass := add(gasToPass, 2300) // stipend TODO + gasUsed := add(gasUsed, 9000) // positive_value_cost if isAddrEmpty(addr) { gasUsed := add(gasUsed, 25000) // value_to_empty_account_cost } } - { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) - gasUsed := add(gasUsed, maxExpand) - } - evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGasForCall(evmGasLeft, gasToPass) + evmGasLeft := sub(evmGasLeft, gasToPass) + + if gt(value, 0) { + gasToPass := add(gasToPass, 2300) + } let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) if precompileCost { if lt(gasToPass, precompileCost) { - evmGasLeft := chargeGas(evmGasLeft, gasToPass) gasToPass := 0 } } @@ -730,20 +730,17 @@ object "EvmEmulator" { retSize ) - let gasUsedByCall := sub(gasToPass, frameGasLeft) - if precompileCost { switch success case 0 { - gasUsedByCall := gasToPass + frameGasLeft := 0 } default { - gasUsedByCall := precompileCost + frameGasLeft := sub(gasToPass, precompileCost) } } - newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) - + newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } @@ -767,19 +764,15 @@ object "EvmEmulator" { gasUsed := 2600 } - { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) - gasUsed := add(gasUsed, maxExpand) - } + gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGasForCall(evmGasLeft, gasToPass) + evmGasLeft := sub(evmGasLeft, gasToPass) let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) if precompileCost { if lt(gasToPass, precompileCost) { - evmGasLeft := chargeGas(evmGasLeft, gasToPass) gasToPass := 0 } } @@ -793,25 +786,22 @@ object "EvmEmulator" { retSize ) - let gasUsedByCall := sub(gasToPass, frameGasLeft) - if precompileCost { switch success case 0 { - gasUsedByCall := gasToPass + frameGasLeft := 0 } default { - gasUsedByCall := precompileCost + frameGasLeft := sub(gasToPass, precompileCost) } } - newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) - + newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } - function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEvmGasLeft, sp, stackHead { + function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGasLeft, sp, stackHead { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 6) @@ -831,10 +821,7 @@ object "EvmEmulator" { gasUsed := 2600 } - { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) - gasUsed := add(gasUsed, maxExpand) - } + gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) @@ -843,6 +830,7 @@ object "EvmEmulator" { } gasToPass := capGasForCall(evmGasLeft, gasToPass) + evmGasLeft := sub(evmGasLeft, gasToPass) _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( @@ -855,10 +843,8 @@ object "EvmEmulator" { ) let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - let gasUsed := sub(gasToPass, frameGasLeft) - - newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } @@ -3797,7 +3783,7 @@ object "EvmEmulator" { // 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, 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. // 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. let gasUsed := 100 // warm address access cost @@ -3805,28 +3791,28 @@ object "EvmEmulator" { gasUsed := 2600 // cold address access cost } + // memory_expansion_cost + gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + if gt(value, 0) { - gasUsed := add(gasUsed, 6700) // positive_value_cost - stipend - gasToPass := add(gasToPass, 2300) // stipend TODO + gasUsed := add(gasUsed, 9000) // positive_value_cost if isAddrEmpty(addr) { gasUsed := add(gasUsed, 25000) // value_to_empty_account_cost } } - { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) - gasUsed := add(gasUsed, maxExpand) - } - evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGasForCall(evmGasLeft, gasToPass) + evmGasLeft := sub(evmGasLeft, gasToPass) + + if gt(value, 0) { + gasToPass := add(gasToPass, 2300) + } let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) if precompileCost { if lt(gasToPass, precompileCost) { - evmGasLeft := chargeGas(evmGasLeft, gasToPass) gasToPass := 0 } } @@ -3841,20 +3827,17 @@ object "EvmEmulator" { retSize ) - let gasUsedByCall := sub(gasToPass, frameGasLeft) - if precompileCost { switch success case 0 { - gasUsedByCall := gasToPass + frameGasLeft := 0 } default { - gasUsedByCall := precompileCost + frameGasLeft := sub(gasToPass, precompileCost) } } - newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) - + newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } @@ -3878,19 +3861,15 @@ object "EvmEmulator" { gasUsed := 2600 } - { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) - gasUsed := add(gasUsed, maxExpand) - } + gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGasForCall(evmGasLeft, gasToPass) + evmGasLeft := sub(evmGasLeft, gasToPass) let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) if precompileCost { if lt(gasToPass, precompileCost) { - evmGasLeft := chargeGas(evmGasLeft, gasToPass) gasToPass := 0 } } @@ -3904,25 +3883,22 @@ object "EvmEmulator" { retSize ) - let gasUsedByCall := sub(gasToPass, frameGasLeft) - if precompileCost { switch success case 0 { - gasUsedByCall := gasToPass + frameGasLeft := 0 } default { - gasUsedByCall := precompileCost + frameGasLeft := sub(gasToPass, precompileCost) } } - newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) - + newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } - function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEvmGasLeft, sp, stackHead { + function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGasLeft, sp, stackHead { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 6) @@ -3942,10 +3918,7 @@ object "EvmEmulator" { gasUsed := 2600 } - { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) - gasUsed := add(gasUsed, maxExpand) - } + gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) @@ -3954,6 +3927,7 @@ object "EvmEmulator" { } gasToPass := capGasForCall(evmGasLeft, gasToPass) + evmGasLeft := sub(evmGasLeft, gasToPass) _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( @@ -3966,10 +3940,8 @@ object "EvmEmulator" { ) let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - let gasUsed := sub(gasToPass, frameGasLeft) - - newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 2d628d0f9..755f82f5e 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -626,7 +626,7 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe // 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, 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. // 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. let gasUsed := 100 // warm address access cost @@ -634,28 +634,28 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe gasUsed := 2600 // cold address access cost } + // memory_expansion_cost + gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + if gt(value, 0) { - gasUsed := add(gasUsed, 6700) // positive_value_cost - stipend - gasToPass := add(gasToPass, 2300) // stipend TODO + gasUsed := add(gasUsed, 9000) // positive_value_cost if isAddrEmpty(addr) { gasUsed := add(gasUsed, 25000) // value_to_empty_account_cost } } - { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) - gasUsed := add(gasUsed, maxExpand) - } - evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGasForCall(evmGasLeft, gasToPass) + evmGasLeft := sub(evmGasLeft, gasToPass) + + if gt(value, 0) { + gasToPass := add(gasToPass, 2300) + } let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) if precompileCost { if lt(gasToPass, precompileCost) { - evmGasLeft := chargeGas(evmGasLeft, gasToPass) gasToPass := 0 } } @@ -670,20 +670,17 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe retSize ) - let gasUsedByCall := sub(gasToPass, frameGasLeft) - if precompileCost { switch success case 0 { - gasUsedByCall := gasToPass + frameGasLeft := 0 } default { - gasUsedByCall := precompileCost + frameGasLeft := sub(gasToPass, precompileCost) } } - newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) - + newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } @@ -707,19 +704,15 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s gasUsed := 2600 } - { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) - gasUsed := add(gasUsed, maxExpand) - } + gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) - gasToPass := capGasForCall(evmGasLeft, gasToPass) + evmGasLeft := sub(evmGasLeft, gasToPass) let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) if precompileCost { if lt(gasToPass, precompileCost) { - evmGasLeft := chargeGas(evmGasLeft, gasToPass) gasToPass := 0 } } @@ -733,25 +726,22 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s retSize ) - let gasUsedByCall := sub(gasToPass, frameGasLeft) - if precompileCost { switch success case 0 { - gasUsedByCall := gasToPass + frameGasLeft := 0 } default { - gasUsedByCall := precompileCost + frameGasLeft := sub(gasToPass, precompileCost) } } - newGasLeft := chargeGas(evmGasLeft, gasUsedByCall) - + newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } -function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEvmGasLeft, sp, stackHead { +function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGasLeft, sp, stackHead { let addr, gasToPass, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 6) @@ -771,10 +761,7 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEv gasUsed := 2600 } - { - let maxExpand := getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) - gasUsed := add(gasUsed, maxExpand) - } + gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) @@ -783,6 +770,7 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEv } gasToPass := capGasForCall(evmGasLeft, gasToPass) + evmGasLeft := sub(evmGasLeft, gasToPass) _pushEVMFrame(gasToPass, isStatic) let success := delegatecall( @@ -795,10 +783,8 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newEv ) let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) - let gasUsed := sub(gasToPass, frameGasLeft) - - newEvmGasLeft := chargeGas(evmGasLeft, gasUsed) + newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } From e1eb15bad84fe6a0b3fbceedf0afe4d126043c3a Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 27 Oct 2024 13:20:05 +0100 Subject: [PATCH 113/183] fix(EVM): Remove gas calculation logic for unsupported precompiles; draft modexp gas model (#1022) --- system-contracts/contracts/EvmEmulator.yul | 238 +++--------------- .../EvmEmulatorFunctions.template.yul | 117 ++------- .../drafted/EvmEmulatorModexpGas.template.yul | 85 +++++++ 3 files changed, 135 insertions(+), 305 deletions(-) create mode 100644 system-contracts/evm-emulator/drafted/EvmEmulatorModexpGas.template.yul diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 19a8d41a6..44f6957b3 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -395,21 +395,6 @@ object "EvmEmulator" { } } - 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 - } - // 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(offset, size) -> gasCost { @@ -733,7 +718,7 @@ object "EvmEmulator" { if precompileCost { switch success case 0 { - frameGasLeft := 0 + frameGasLeft := 0 // consume all provided gas } default { frameGasLeft := sub(gasToPass, precompileCost) @@ -789,7 +774,7 @@ object "EvmEmulator" { if precompileCost { switch success case 0 { - frameGasLeft := 0 + frameGasLeft := 0 // consume all provided gas } default { frameGasLeft := sub(gasToPass, precompileCost) @@ -825,6 +810,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, gasUsed) + // it is not possible to delegatecall precompiles if iszero(_isEVM(addr)) { revertWithGas(evmGasLeft) } @@ -936,94 +922,20 @@ object "EvmEmulator" { gasToCharge := 3000 } case 0x02 { // SHA2-256 - gasToCharge := 60 let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 - gasToCharge := add(gasToCharge, mul(12, dataWordSize)) + gasToCharge := add(60, 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)) + // We do not support RIPEMD-160 + gasToCharge := 0 } 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 + gasToCharge := add(15, mul(3, dataWordSize)) + } 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)) + // We do not support modexp + gasToCharge := 0 } // ecAdd ecMul ecPairing EIP below // https://eips.ethereum.org/EIPS/eip-1108 @@ -1040,13 +952,16 @@ object "EvmEmulator" { // 34,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, 34000)) + gasToCharge := add(45000, mul(k, 34000)) } case 0x09 { // blake2f - // argsOffset[0; 3] (4 bytes) Number of rounds (big-endian uint) - gasToCharge := and(mload(argsOffset), 0xFFFFFFFF) // last 4bytes + // We do not support blake2f + gasToCharge := 0 + } + case 0x0a { // kzg point evaluation + // We do not support kzg point evaluation + gasToCharge := 0 } default { gasToCharge := 0 @@ -3492,21 +3407,6 @@ object "EvmEmulator" { } } - 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 - } - // 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(offset, size) -> gasCost { @@ -3830,7 +3730,7 @@ object "EvmEmulator" { if precompileCost { switch success case 0 { - frameGasLeft := 0 + frameGasLeft := 0 // consume all provided gas } default { frameGasLeft := sub(gasToPass, precompileCost) @@ -3886,7 +3786,7 @@ object "EvmEmulator" { if precompileCost { switch success case 0 { - frameGasLeft := 0 + frameGasLeft := 0 // consume all provided gas } default { frameGasLeft := sub(gasToPass, precompileCost) @@ -3922,6 +3822,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, gasUsed) + // it is not possible to delegatecall precompiles if iszero(_isEVM(addr)) { revertWithGas(evmGasLeft) } @@ -4033,94 +3934,20 @@ object "EvmEmulator" { gasToCharge := 3000 } case 0x02 { // SHA2-256 - gasToCharge := 60 let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 - gasToCharge := add(gasToCharge, mul(12, dataWordSize)) + gasToCharge := add(60, 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)) + // We do not support RIPEMD-160 + gasToCharge := 0 } 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 + gasToCharge := add(15, mul(3, dataWordSize)) + } 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)) + // We do not support modexp + gasToCharge := 0 } // ecAdd ecMul ecPairing EIP below // https://eips.ethereum.org/EIPS/eip-1108 @@ -4137,13 +3964,16 @@ object "EvmEmulator" { // 34,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, 34000)) + gasToCharge := add(45000, mul(k, 34000)) } case 0x09 { // blake2f - // argsOffset[0; 3] (4 bytes) Number of rounds (big-endian uint) - gasToCharge := and(mload(argsOffset), 0xFFFFFFFF) // last 4bytes + // We do not support blake2f + gasToCharge := 0 + } + case 0x0a { // kzg point evaluation + // We do not support kzg point evaluation + gasToCharge := 0 } default { gasToCharge := 0 diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 755f82f5e..317be4109 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -335,21 +335,6 @@ function getMax(a, b) -> max { } } -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 -} - // 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(offset, size) -> gasCost { @@ -673,7 +658,7 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe if precompileCost { switch success case 0 { - frameGasLeft := 0 + frameGasLeft := 0 // consume all provided gas } default { frameGasLeft := sub(gasToPass, precompileCost) @@ -729,7 +714,7 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s if precompileCost { switch success case 0 { - frameGasLeft := 0 + frameGasLeft := 0 // consume all provided gas } default { frameGasLeft := sub(gasToPass, precompileCost) @@ -765,6 +750,7 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGa evmGasLeft := chargeGas(evmGasLeft, gasUsed) + // it is not possible to delegatecall precompiles if iszero(_isEVM(addr)) { revertWithGas(evmGasLeft) } @@ -876,94 +862,20 @@ function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { gasToCharge := 3000 } case 0x02 { // SHA2-256 - gasToCharge := 60 let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 - gasToCharge := add(gasToCharge, mul(12, dataWordSize)) + gasToCharge := add(60, 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)) + // We do not support RIPEMD-160 + gasToCharge := 0 } case 0x04 { // identity - gasToCharge := 15 let dataWordSize := shr(5, add(argsSize, 31)) // (argsSize+31)/32 - gasToCharge := add(gasToCharge, mul(3, dataWordSize)) + gasToCharge := add(15, 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)) + // We do not support modexp + gasToCharge := 0 } // ecAdd ecMul ecPairing EIP below // https://eips.ethereum.org/EIPS/eip-1108 @@ -980,13 +892,16 @@ function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { // 34,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, 34000)) + gasToCharge := add(45000, mul(k, 34000)) } case 0x09 { // blake2f - // argsOffset[0; 3] (4 bytes) Number of rounds (big-endian uint) - gasToCharge := and(mload(argsOffset), 0xFFFFFFFF) // last 4bytes + // We do not support blake2f + gasToCharge := 0 + } + case 0x0a { // kzg point evaluation + // We do not support kzg point evaluation + gasToCharge := 0 } default { gasToCharge := 0 diff --git a/system-contracts/evm-emulator/drafted/EvmEmulatorModexpGas.template.yul b/system-contracts/evm-emulator/drafted/EvmEmulatorModexpGas.template.yul new file mode 100644 index 000000000..ba018dae1 --- /dev/null +++ b/system-contracts/evm-emulator/drafted/EvmEmulatorModexpGas.template.yul @@ -0,0 +1,85 @@ +/// (!) Note: this code is unused until we have modexp precompile support +/// This is draft, it is necessary to take into account the case when argsSize is less than expected (data is truncated and padded with zeroes) +/// Also we need to check sanity of Bsize, Esize, Msize + +/// @dev credit to https://github.com/PaulRBerg/prb-math/blob/280fc5f77e1b21b9c54013aac51966be33f4a410/src/Common.sol#L323 +function msb(x) -> result { + let factor := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) // 2^128 + x := shr(factor, x) + result := or(result, factor) + factor := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF)) // 2^64 + x := shr(factor, x) + result := or(result, factor) + factor := shl(5, gt(x, 0xFFFFFFFF)) // 2^32 + x := shr(factor, x) + result := or(result, factor) + factor := shl(4, gt(x, 0xFFFF)) // 2^16 + x := shr(factor, x) + result := or(result, factor) + factor := shl(3, gt(x, 0xFF)) // 2^8 + x := shr(factor, x) + result := or(result, factor) + factor := shl(2, gt(x, 0xF)) // 2^4 + x := shr(factor, x) + result := or(result, factor) + factor := shl(1, gt(x, 0x3)) // 2^2 + x := shr(factor, x) + result := or(result, factor) + factor := gt(x, 0x1) // 2^1 + // No need to shift x any more. + result := or(result, factor) +} + +// modexp gas cost EIP below +// https://eips.ethereum.org/EIPS/eip-2565 +// [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 +let Bsize := mload(argsOffset) +let Esize := mload(add(argsOffset, 0x20)) + +let mulComplex +{ + // mult_complexity(Bsize, Msize), EIP-2565 + let words := getMax(Bsize, mload(add(argsOffset, 0x40))) + words := div(add(words, 7), 8) // TODO OVERFLOW CHECKS + mulComplex := mul(words, words) +} + +/* +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) +*/ +// [96 + Bsize; 96 + Bsize + Esize] E +let iterationCount := 0 +let expOffset := add(add(argsOffset, 0x60), Bsize) +switch gt(Esize, 32) +case 0 { // if exponent_length <= 32 + let exponent := mload(expOffset) // load 32 bytes + exponent := shr(sub(32, Esize), exponent) // shift to the right if Esize not 32 bytes + + // if exponent_length <= 32 and exponent == 0: iteration_count = 0 + // elif exponent_length <= 32: iteration_count = exponent.bit_length() - 1 + if exponent { + iterationCount := msb(exponent) + } +} +default { // elif exponent_length > 32 + // elif exponent_length > 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent & (2**256 - 1)).bit_length() - 1) + + // load last 32 bytes of exponent + let exponentLast256 := mload(add(expOffset, sub(Esize, 32))) + iterationCount := add(mul(8, sub(Esize, 32)), msb(exponentLast256)) +} +if iszero(iterationCount) { + iterationCount := 1 +} + +/* + return max(200, math.floor(multiplication_complexity * iteration_count / 3)) +*/ +gasToCharge := getMax(200, div(mul(mulComplex, iterationCount), 3)) \ No newline at end of file From c7a1f3884290b068cb3da24597ede9d251e9fd08 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 27 Oct 2024 13:48:41 +0100 Subject: [PATCH 114/183] Feat(EVM): Use different memory layouts for constructor and deployed contract (#1023) --- system-contracts/SystemContractsHashes.json | 8 ++++---- system-contracts/contracts/EvmEmulator.yul | 12 ++++++++++-- .../evm-emulator/EvmEmulator.template.yul | 8 ++++++++ .../evm-emulator/EvmEmulatorFunctions.template.yul | 2 +- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 4adbab2d1..a0aefd206 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -108,8 +108,8 @@ "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c5a6801732584ea1804b91e5621ac25460be6b91196fc4d68fd3a65105", - "sourceCodeHash": "0xc5ce25a94e3b510183635dd2fe0152dbcaa705bc8802fb3a4390253b5af3aa0a" + "bytecodeHash": "0x010001c516b1721bd4745d8d3a36607d4f6b65c0d51dcb1b5801aaf0234293cc", + "sourceCodeHash": "0xe2f6eb015d260aafe9405b28ef3ec27921add4de7f329b7ef61e0aa6c9365e29" }, { "contractName": "EventWriter", @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000d1da56c97d7554e0e9c8397a970b5a44c569aab6fb6661f820c5ae3e58e", - "sourceCodeHash": "0xb6b321ccc368ca848ca6675eaf968dedd4b4da388d74829cd3fb9927f4550071" + "bytecodeHash": "0x01000d6d51fe13baa8278266bb8775c03df377c8b0aa6ebca6c8d98a096b7bb2", + "sourceCodeHash": "0x676b1652efec61f16eb271efda30e3a695681ce7b2f1a509b33c4afb15c55723" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 44f6957b3..12f70efe4 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1,5 +1,9 @@ object "EvmEmulator" { code { + function MAX_POSSIBLE_ACTIVE_BYTECODE() -> max { + max := MAX_POSSIBLE_INIT_BYTECODE() + } + /// @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. @@ -143,7 +147,7 @@ object "EvmEmulator" { } function MEM_OFFSET() -> offset { - offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_INIT_BYTECODE()) + offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_ACTIVE_BYTECODE()) } function MEM_OFFSET_INNER() -> offset { @@ -3070,6 +3074,10 @@ object "EvmEmulator" { } object "EvmEmulator_deployed" { code { + function MAX_POSSIBLE_ACTIVE_BYTECODE() -> max { + max := MAX_POSSIBLE_DEPLOYED_BYTECODE() + } + //////////////////////////////////////////////////////////////// // CONSTANTS //////////////////////////////////////////////////////////////// @@ -3155,7 +3163,7 @@ object "EvmEmulator" { } function MEM_OFFSET() -> offset { - offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_INIT_BYTECODE()) + offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_ACTIVE_BYTECODE()) } function MEM_OFFSET_INNER() -> offset { diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index 1730a0b8e..02571acf5 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -1,5 +1,9 @@ object "EvmEmulator" { code { + function MAX_POSSIBLE_ACTIVE_BYTECODE() -> max { + max := MAX_POSSIBLE_INIT_BYTECODE() + } + /// @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. @@ -104,6 +108,10 @@ object "EvmEmulator" { } object "EvmEmulator_deployed" { code { + function MAX_POSSIBLE_ACTIVE_BYTECODE() -> max { + max := MAX_POSSIBLE_DEPLOYED_BYTECODE() + } + function $llvm_NoInline_llvm$_simulate( diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 317be4109..6984bbb91 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -83,7 +83,7 @@ function MAX_POSSIBLE_INIT_BYTECODE() -> max { } function MEM_OFFSET() -> offset { - offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_INIT_BYTECODE()) + offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_ACTIVE_BYTECODE()) } function MEM_OFFSET_INNER() -> offset { From 646a408657ac10e5103e2d72f99c7206c062b287 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 27 Oct 2024 15:19:30 +0100 Subject: [PATCH 115/183] fix(EVM): Fix bytecode read operations (#1024) --- system-contracts/contracts/EvmEmulator.yul | 203 +++++++++--------- .../evm-emulator/EvmEmulator.template.yul | 1 + .../EvmEmulatorFunctions.template.yul | 28 +-- .../evm-emulator/EvmEmulatorLoop.template.yul | 73 ++++--- 4 files changed, 158 insertions(+), 147 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 12f70efe4..ab5b4deb3 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -20,6 +20,7 @@ object "EvmEmulator" { } mstore(bytecodeLengthOffset, size) + mstore(EMPTY_CODE_OFFSET(), 0) copyActivePtrData(bytecodeOffset, 0, size) } @@ -146,10 +147,15 @@ object "EvmEmulator" { max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE()) // EIP-3860 } - function MEM_OFFSET() -> offset { + // reserved empty slot to simplify PUSH N opcodes + function EMPTY_CODE_OFFSET() -> offset { offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_ACTIVE_BYTECODE()) } + function MEM_OFFSET() -> offset { + offset := add(EMPTY_CODE_OFFSET(), 32) + } + function MEM_OFFSET_INNER() -> offset { offset := add(MEM_OFFSET(), 32) } @@ -241,20 +247,18 @@ object "EvmEmulator" { } } - // 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) + // It is the responsibility of the caller to ensure that ip is correct + function readIP(ip, bytecodeEndOffset) -> opcode { + if lt(ip, bytecodeEndOffset) { + opcode := and(mload(sub(ip, 31)), 0xff) } - - opcode := and(mload(sub(ip, 31)), 0xff) + // STOP else } - 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)) + // It is the responsibility of the caller to ensure that start and length is correct + function readBytes(start, length) -> value { + value := shr(mul(8, sub(32, length)), mload(start)) + // will be padded by zeroes if out of bounds (we have reserved EMPTY_CODE_OFFSET() slot) } function getCodeAddress() -> addr { @@ -389,6 +393,7 @@ object "EvmEmulator" { MAX_POSSIBLE_DEPLOYED_BYTECODE() ) + mstore(EMPTY_CODE_OFFSET(), 0) mstore(BYTECODE_OFFSET(), codeLen) } @@ -1246,13 +1251,12 @@ object "EvmEmulator" { // 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 stackHead - let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) + let bytecodeEndOffset := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 32) for { } true { } { - opcode := readIP(ip,maxAcceptablePos) + let opcode := readIP(ip, bytecodeEndOffset) switch opcode case 0x00 { // OP_STOP @@ -1959,7 +1963,7 @@ object "EvmEmulator" { ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST - let nextOpcode := readIP(ip,maxAcceptablePos) + let nextOpcode := readIP(ip, bytecodeEndOffset) if iszero(eq(nextOpcode, 0x5B)) { panic() } @@ -1985,7 +1989,7 @@ object "EvmEmulator" { ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST - let nextOpcode := readIP(ip, maxAcceptablePos) + let nextOpcode := readIP(ip, bytecodeEndOffset) if iszero(eq(nextOpcode, 0x5B)) { panic() } @@ -2074,7 +2078,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 1) + let value := readBytes(ip, 1) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 1) @@ -2083,7 +2087,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 2) + let value := readBytes(ip, 2) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 2) @@ -2092,7 +2096,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 3) + let value := readBytes(ip, 3) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 3) @@ -2101,7 +2105,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 4) + let value := readBytes(ip, 4) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 4) @@ -2110,7 +2114,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 5) + let value := readBytes(ip, 5) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 5) @@ -2119,7 +2123,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 6) + let value := readBytes(ip, 6) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 6) @@ -2128,7 +2132,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 7) + let value := readBytes(ip, 7) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 7) @@ -2137,7 +2141,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 8) + let value := readBytes(ip, 8) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 8) @@ -2146,7 +2150,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 9) + let value := readBytes(ip, 9) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 9) @@ -2155,7 +2159,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 10) + let value := readBytes(ip, 10) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 10) @@ -2164,7 +2168,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 11) + let value := readBytes(ip, 11) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 11) @@ -2173,7 +2177,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 12) + let value := readBytes(ip, 12) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 12) @@ -2182,7 +2186,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 13) + let value := readBytes(ip, 13) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 13) @@ -2191,7 +2195,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 14) + let value := readBytes(ip, 14) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 14) @@ -2200,7 +2204,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 15) + let value := readBytes(ip, 15) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 15) @@ -2209,7 +2213,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 16) + let value := readBytes(ip, 16) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 16) @@ -2218,7 +2222,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 17) + let value := readBytes(ip, 17) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 17) @@ -2227,7 +2231,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 18) + let value := readBytes(ip, 18) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 18) @@ -2236,7 +2240,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 19) + let value := readBytes(ip, 19) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 19) @@ -2245,7 +2249,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 20) + let value := readBytes(ip, 20) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 20) @@ -2254,7 +2258,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 21) + let value := readBytes(ip, 21) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 21) @@ -2263,7 +2267,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 22) + let value := readBytes(ip, 22) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 22) @@ -2272,7 +2276,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 23) + let value := readBytes(ip, 23) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 23) @@ -2281,7 +2285,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 24) + let value := readBytes(ip, 24) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 24) @@ -2290,7 +2294,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 25) + let value := readBytes(ip, 25) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 25) @@ -2299,7 +2303,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 26) + let value := readBytes(ip, 26) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 26) @@ -2308,7 +2312,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 27) + let value := readBytes(ip, 27) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 27) @@ -2317,7 +2321,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 28) + let value := readBytes(ip, 28) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 28) @@ -2326,7 +2330,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 29) + let value := readBytes(ip, 29) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 29) @@ -2335,7 +2339,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 30) + let value := readBytes(ip, 30) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 30) @@ -2344,7 +2348,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 31) + let value := readBytes(ip, 31) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 31) @@ -2353,7 +2357,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 32) + let value := readBytes(ip, 32) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 32) @@ -3162,10 +3166,15 @@ object "EvmEmulator" { max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE()) // EIP-3860 } - function MEM_OFFSET() -> offset { + // reserved empty slot to simplify PUSH N opcodes + function EMPTY_CODE_OFFSET() -> offset { offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_ACTIVE_BYTECODE()) } + function MEM_OFFSET() -> offset { + offset := add(EMPTY_CODE_OFFSET(), 32) + } + function MEM_OFFSET_INNER() -> offset { offset := add(MEM_OFFSET(), 32) } @@ -3257,20 +3266,18 @@ object "EvmEmulator" { } } - // 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) + // It is the responsibility of the caller to ensure that ip is correct + function readIP(ip, bytecodeEndOffset) -> opcode { + if lt(ip, bytecodeEndOffset) { + opcode := and(mload(sub(ip, 31)), 0xff) } - - opcode := and(mload(sub(ip, 31)), 0xff) + // STOP else } - 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)) + // It is the responsibility of the caller to ensure that start and length is correct + function readBytes(start, length) -> value { + value := shr(mul(8, sub(32, length)), mload(start)) + // will be padded by zeroes if out of bounds (we have reserved EMPTY_CODE_OFFSET() slot) } function getCodeAddress() -> addr { @@ -3405,6 +3412,7 @@ object "EvmEmulator" { MAX_POSSIBLE_DEPLOYED_BYTECODE() ) + mstore(EMPTY_CODE_OFFSET(), 0) mstore(BYTECODE_OFFSET(), codeLen) } @@ -4262,13 +4270,12 @@ object "EvmEmulator" { // 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 stackHead - let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) + let bytecodeEndOffset := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 32) for { } true { } { - opcode := readIP(ip,maxAcceptablePos) + let opcode := readIP(ip, bytecodeEndOffset) switch opcode case 0x00 { // OP_STOP @@ -4975,7 +4982,7 @@ object "EvmEmulator" { ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST - let nextOpcode := readIP(ip,maxAcceptablePos) + let nextOpcode := readIP(ip, bytecodeEndOffset) if iszero(eq(nextOpcode, 0x5B)) { panic() } @@ -5001,7 +5008,7 @@ object "EvmEmulator" { ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST - let nextOpcode := readIP(ip, maxAcceptablePos) + let nextOpcode := readIP(ip, bytecodeEndOffset) if iszero(eq(nextOpcode, 0x5B)) { panic() } @@ -5090,7 +5097,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 1) + let value := readBytes(ip, 1) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 1) @@ -5099,7 +5106,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 2) + let value := readBytes(ip, 2) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 2) @@ -5108,7 +5115,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 3) + let value := readBytes(ip, 3) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 3) @@ -5117,7 +5124,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 4) + let value := readBytes(ip, 4) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 4) @@ -5126,7 +5133,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 5) + let value := readBytes(ip, 5) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 5) @@ -5135,7 +5142,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 6) + let value := readBytes(ip, 6) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 6) @@ -5144,7 +5151,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 7) + let value := readBytes(ip, 7) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 7) @@ -5153,7 +5160,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 8) + let value := readBytes(ip, 8) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 8) @@ -5162,7 +5169,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 9) + let value := readBytes(ip, 9) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 9) @@ -5171,7 +5178,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 10) + let value := readBytes(ip, 10) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 10) @@ -5180,7 +5187,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 11) + let value := readBytes(ip, 11) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 11) @@ -5189,7 +5196,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 12) + let value := readBytes(ip, 12) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 12) @@ -5198,7 +5205,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 13) + let value := readBytes(ip, 13) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 13) @@ -5207,7 +5214,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 14) + let value := readBytes(ip, 14) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 14) @@ -5216,7 +5223,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 15) + let value := readBytes(ip, 15) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 15) @@ -5225,7 +5232,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 16) + let value := readBytes(ip, 16) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 16) @@ -5234,7 +5241,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 17) + let value := readBytes(ip, 17) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 17) @@ -5243,7 +5250,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 18) + let value := readBytes(ip, 18) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 18) @@ -5252,7 +5259,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 19) + let value := readBytes(ip, 19) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 19) @@ -5261,7 +5268,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 20) + let value := readBytes(ip, 20) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 20) @@ -5270,7 +5277,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 21) + let value := readBytes(ip, 21) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 21) @@ -5279,7 +5286,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 22) + let value := readBytes(ip, 22) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 22) @@ -5288,7 +5295,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 23) + let value := readBytes(ip, 23) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 23) @@ -5297,7 +5304,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 24) + let value := readBytes(ip, 24) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 24) @@ -5306,7 +5313,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 25) + let value := readBytes(ip, 25) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 25) @@ -5315,7 +5322,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 26) + let value := readBytes(ip, 26) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 26) @@ -5324,7 +5331,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 27) + let value := readBytes(ip, 27) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 27) @@ -5333,7 +5340,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 28) + let value := readBytes(ip, 28) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 28) @@ -5342,7 +5349,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 29) + let value := readBytes(ip, 29) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 29) @@ -5351,7 +5358,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 30) + let value := readBytes(ip, 30) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 30) @@ -5360,7 +5367,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 31) + let value := readBytes(ip, 31) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 31) @@ -5369,7 +5376,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 32) + let value := readBytes(ip, 32) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 32) diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index 02571acf5..db7499ec3 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -20,6 +20,7 @@ object "EvmEmulator" { } mstore(bytecodeLengthOffset, size) + mstore(EMPTY_CODE_OFFSET(), 0) copyActivePtrData(bytecodeOffset, 0, size) } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 6984bbb91..b93e7dc8b 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -82,10 +82,15 @@ function MAX_POSSIBLE_INIT_BYTECODE() -> max { max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE()) // EIP-3860 } -function MEM_OFFSET() -> offset { +// reserved empty slot to simplify PUSH N opcodes +function EMPTY_CODE_OFFSET() -> offset { offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_ACTIVE_BYTECODE()) } +function MEM_OFFSET() -> offset { + offset := add(EMPTY_CODE_OFFSET(), 32) +} + function MEM_OFFSET_INNER() -> offset { offset := add(MEM_OFFSET(), 32) } @@ -177,20 +182,18 @@ function checkOverflow(data1, data2) { } } -// 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) +// It is the responsibility of the caller to ensure that ip is correct +function readIP(ip, bytecodeEndOffset) -> opcode { + if lt(ip, bytecodeEndOffset) { + opcode := and(mload(sub(ip, 31)), 0xff) } - - opcode := and(mload(sub(ip, 31)), 0xff) + // STOP else } -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)) +// It is the responsibility of the caller to ensure that start and length is correct +function readBytes(start, length) -> value { + value := shr(mul(8, sub(32, length)), mload(start)) + // will be padded by zeroes if out of bounds (we have reserved EMPTY_CODE_OFFSET() slot) } function getCodeAddress() -> addr { @@ -325,6 +328,7 @@ function getDeployedBytecode() { MAX_POSSIBLE_DEPLOYED_BYTECODE() ) + mstore(EMPTY_CODE_OFFSET(), 0) mstore(BYTECODE_OFFSET(), codeLen) } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 52d04d072..319edb7e0 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -3,13 +3,12 @@ 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 stackHead -let maxAcceptablePos := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 31) +let bytecodeEndOffset := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 32) for { } true { } { - opcode := readIP(ip,maxAcceptablePos) + let opcode := readIP(ip, bytecodeEndOffset) switch opcode case 0x00 { // OP_STOP @@ -716,7 +715,7 @@ for { } true { } { ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST - let nextOpcode := readIP(ip,maxAcceptablePos) + let nextOpcode := readIP(ip, bytecodeEndOffset) if iszero(eq(nextOpcode, 0x5B)) { panic() } @@ -742,7 +741,7 @@ for { } true { } { ip := add(add(BYTECODE_OFFSET(), 32), counter) // Check next opcode is JUMPDEST - let nextOpcode := readIP(ip, maxAcceptablePos) + let nextOpcode := readIP(ip, bytecodeEndOffset) if iszero(eq(nextOpcode, 0x5B)) { panic() } @@ -831,7 +830,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 1) + let value := readBytes(ip, 1) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 1) @@ -840,7 +839,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 2) + let value := readBytes(ip, 2) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 2) @@ -849,7 +848,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 3) + let value := readBytes(ip, 3) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 3) @@ -858,7 +857,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 4) + let value := readBytes(ip, 4) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 4) @@ -867,7 +866,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 5) + let value := readBytes(ip, 5) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 5) @@ -876,7 +875,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 6) + let value := readBytes(ip, 6) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 6) @@ -885,7 +884,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 7) + let value := readBytes(ip, 7) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 7) @@ -894,7 +893,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 8) + let value := readBytes(ip, 8) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 8) @@ -903,7 +902,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 9) + let value := readBytes(ip, 9) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 9) @@ -912,7 +911,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 10) + let value := readBytes(ip, 10) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 10) @@ -921,7 +920,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 11) + let value := readBytes(ip, 11) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 11) @@ -930,7 +929,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 12) + let value := readBytes(ip, 12) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 12) @@ -939,7 +938,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 13) + let value := readBytes(ip, 13) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 13) @@ -948,7 +947,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 14) + let value := readBytes(ip, 14) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 14) @@ -957,7 +956,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 15) + let value := readBytes(ip, 15) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 15) @@ -966,7 +965,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 16) + let value := readBytes(ip, 16) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 16) @@ -975,7 +974,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 17) + let value := readBytes(ip, 17) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 17) @@ -984,7 +983,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 18) + let value := readBytes(ip, 18) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 18) @@ -993,7 +992,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 19) + let value := readBytes(ip, 19) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 19) @@ -1002,7 +1001,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 20) + let value := readBytes(ip, 20) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 20) @@ -1011,7 +1010,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 21) + let value := readBytes(ip, 21) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 21) @@ -1020,7 +1019,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 22) + let value := readBytes(ip, 22) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 22) @@ -1029,7 +1028,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 23) + let value := readBytes(ip, 23) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 23) @@ -1038,7 +1037,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 24) + let value := readBytes(ip, 24) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 24) @@ -1047,7 +1046,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 25) + let value := readBytes(ip, 25) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 25) @@ -1056,7 +1055,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 26) + let value := readBytes(ip, 26) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 26) @@ -1065,7 +1064,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 27) + let value := readBytes(ip, 27) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 27) @@ -1074,7 +1073,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 28) + let value := readBytes(ip, 28) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 28) @@ -1083,7 +1082,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 29) + let value := readBytes(ip, 29) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 29) @@ -1092,7 +1091,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 30) + let value := readBytes(ip, 30) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 30) @@ -1101,7 +1100,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 31) + let value := readBytes(ip, 31) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 31) @@ -1110,7 +1109,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 3) ip := add(ip, 1) - let value := readBytes(ip, maxAcceptablePos, 32) + let value := readBytes(ip, 32) sp, stackHead := pushStackItem(sp, value, stackHead) ip := add(ip, 32) From 5d6830c16716ef6887f71a9272e78f7fd61feae1 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 27 Oct 2024 15:49:37 +0100 Subject: [PATCH 116/183] fea(EVM): Optimize JUMP gas charge (#1025) --- system-contracts/contracts/EvmEmulator.yul | 8 ++------ .../evm-emulator/EvmEmulatorLoop.template.yul | 4 +--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index ab5b4deb3..dde42c188 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1954,10 +1954,9 @@ object "EvmEmulator" { // 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) + evmGasLeft := chargeGas(evmGasLeft, 9) // charge for OP_JUMP (8) and OP_JUMPDEST (1) immediately let counter - counter, sp, stackHead := popStackItem(sp, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) @@ -1969,7 +1968,6 @@ object "EvmEmulator" { } // execute JUMPDEST immediately - evmGasLeft := chargeGas(evmGasLeft, 1) ip := add(ip, 1) } case 0x57 { // OP_JUMPI @@ -4973,10 +4971,9 @@ object "EvmEmulator" { // 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) + evmGasLeft := chargeGas(evmGasLeft, 9) // charge for OP_JUMP (8) and OP_JUMPDEST (1) immediately let counter - counter, sp, stackHead := popStackItem(sp, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) @@ -4988,7 +4985,6 @@ object "EvmEmulator" { } // execute JUMPDEST immediately - evmGasLeft := chargeGas(evmGasLeft, 1) ip := add(ip, 1) } case 0x57 { // OP_JUMPI diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 319edb7e0..22efdd53f 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -706,10 +706,9 @@ for { } true { } { // 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) + evmGasLeft := chargeGas(evmGasLeft, 9) // charge for OP_JUMP (8) and OP_JUMPDEST (1) immediately let counter - counter, sp, stackHead := popStackItem(sp, stackHead) ip := add(add(BYTECODE_OFFSET(), 32), counter) @@ -721,7 +720,6 @@ for { } true { } { } // execute JUMPDEST immediately - evmGasLeft := chargeGas(evmGasLeft, 1) ip := add(ip, 1) } case 0x57 { // OP_JUMPI From 8981dec306917262e42568fe16176cb2d71cd4ca Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 27 Oct 2024 17:19:59 +0100 Subject: [PATCH 117/183] chore(EVM): Cleanup (#1026) --- system-contracts/SystemContractsHashes.json | 38 +- system-contracts/contracts/Constants.sol | 5 +- .../contracts/ContractDeployer.sol | 4 +- system-contracts/contracts/DefaultAccount.sol | 1 - system-contracts/contracts/EvmEmulator.yul | 330 +++++++----------- .../contracts/SystemContractErrors.sol | 3 +- .../contracts/libraries/Utils.sol | 16 +- .../EvmEmulatorFunctions.template.yul | 165 ++++----- 8 files changed, 220 insertions(+), 342 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index a0aefd206..d595df6a6 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,50 +3,50 @@ "contractName": "AccountCodeStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x01000077fbba7c8f4a3afae79c335eefc97a06bf0960462a02d71620fa511b83", + "bytecodeHash": "0x010000777c28746231003a691b8bb0f9b223ab03a3c411e43b1aaa8027436826", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f10387df0e25384b8e1647ad3d113d073ed9fbb028efcd97354d7265ff", + "bytecodeHash": "0x010006f1b8097e1e177edecd7df3d65dbb8f8139b4c457cffc733bdef0773868", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x01000047b2acbcfc30be1b0e33524acbb9c0546702fa055ab729ff148c5579d3", + "bytecodeHash": "0x0100004727ddd19b221a109fd0719aa01ecb7de4268b6ed14dfd0b45bcc55139", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013f3655427cabae552ce6e029e1faa6bc47b62c24e91629e4ebd94513cd", + "bytecodeHash": "0x0100013fffa9e5ba3f487cd7443293b210b09d15e8a7f77f6e11f677edc9e835", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010006995d45717ae05cb32bf83f20ac6afd3e830256b19e4b4848ffc049dab4", - "sourceCodeHash": "0xbbca34f18754b9910eab2def1363f1535b5b6833ad96f80b8f70d0f8676850e3" + "bytecodeHash": "0x010006992c48504c10c9acb66b6e847fcd2328389a0d2334fb174f981ba5b291", + "sourceCodeHash": "0x9ad8797aa39ae899362ed936542fe13160ef2a2ed95d67c2d66ac62077e61059" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003fe42e51e49f224a09d0e2fb7a6b89c5d9ca7a0c695b0a2df98ffecd08", + "bytecodeHash": "0x0100003ff3ab2e8e975033d54d64a171cf58c793146ebfba6fd04ce302674373", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x010005099e763f853ae58bcecc5f35c0f4892ff38184472fa5649b64a0ed197e", - "sourceCodeHash": "0x62e525189d13e7d59a88cfe834621bc7fb62cd38e2d830f9a1d1e056e229d2c8" + "bytecodeHash": "0x01000509a98e0465c3b9f288422931c4d008f31a3f6c2aae25efd0ffb1bd58ae", + "sourceCodeHash": "0xef448fac6b6f1c217b6495ee134a3553e02dfb920fd46bc71de33672e64d9ab8" }, { "contractName": "EmptyContract", @@ -59,56 +59,56 @@ "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033f23e43c0c20fd5c0921314464e742a44f86c969f16a62a4e9f377af0", + "bytecodeHash": "0x01000033808c6348792b1baecebf5840e441aff76ef6e2a1715ad2dabf4f90f9", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000c19a85edbe703789e796a6cddd924d426967d2d0b265637a273c3a68cb", + "bytecodeHash": "0x010000bb4c0f108c511d5ff44054b6a961561647f1cc1f6db1eb97eaab5580e4", "sourceCodeHash": "0xeb83e3a2ea2f50b93122363b8dd56fbcfe821d11723d849eecbde3d6af1147de" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010002655d4860b50d58dff8202c1262882feda90d04d80cca482111c62449a3", + "bytecodeHash": "0x01000265ad11b9309608bde6568a778510ac188b1c2db1a7119a2ebc74f76c9b", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f3c2c2afd410587562c39eb92a1a9db7a40620620d7a98c30f6fe38aa5", + "bytecodeHash": "0x010000f339b1e3862bac3fa7045aa87ada897107fef091436f1ea508c8761835", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x010000594fa01bdab3cd481702d2b0b15ee374d0cb49d11473b09e64a007d21c", + "bytecodeHash": "0x01000059d44bf38d8f50b1c01be8ee1354ff38d3a787235e12701ce82a6a00b8", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cfb8bbb8324f7d2df3b077d93cf6ac410d1c5353f99f8a4038f2588c2a", + "bytecodeHash": "0x010000cf5c0b2f62856538d58d994976fa069acf385235b7d13e42708f99c475", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x0100004112d30c5df65c36273ecd46356864e2194ad4b43afaeddb6adc66af8e", + "bytecodeHash": "0x010000415057478c53ab74234e8f205d80e935a96f2341c8c72da2ac422b0222", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c516b1721bd4745d8d3a36607d4f6b65c0d51dcb1b5801aaf0234293cc", + "bytecodeHash": "0x010001c508dcad8f1823f20e91164ff035d6077172b188f3d4c840e4fd8e8d88", "sourceCodeHash": "0xe2f6eb015d260aafe9405b28ef3ec27921add4de7f329b7ef61e0aa6c9365e29" }, { @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000d6d51fe13baa8278266bb8775c03df377c8b0aa6ebca6c8d98a096b7bb2", - "sourceCodeHash": "0x676b1652efec61f16eb271efda30e3a695681ce7b2f1a509b33c4afb15c55723" + "bytecodeHash": "0x01000bf9ff70e59cec40743babb8d27f5c9f4c93ff57e8eedb18de1e2c030791", + "sourceCodeHash": "0x4c367f9487ededd71bb93878d46cb41a3c4b1e4799ccaa9f0d76eb25ee9eec82" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index 310ea599e..c77926e2c 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -164,4 +164,7 @@ uint256 constant BLOB_SIZE_BYTES = 126_976; /// @dev Max number of blobs currently supported uint256 constant MAX_NUMBER_OF_BLOBS = 6; -uint32 constant EVM_GAS_STIPEND = 1 << 30; \ No newline at end of file +uint32 constant EVM_GAS_STIPEND = 1 << 30; + +uint8 constant ERA_VM_BYTECODE_FLAG = 1; +uint8 constant EVM_BYTECODE_FLAG = 2; \ No newline at end of file diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 7c5135c83..fbcac4c33 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -465,8 +465,8 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } /// @notice Deploy a certain bytecode on the address. - /// @param _gasToPass TODO - /// @param _sender TODO + /// @param _gasToPass The amount of gas to be passed in constructor + /// @param _sender The deployer 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. diff --git a/system-contracts/contracts/DefaultAccount.sol b/system-contracts/contracts/DefaultAccount.sol index aa6ce50a5..c42d6dbbd 100644 --- a/system-contracts/contracts/DefaultAccount.sol +++ b/system-contracts/contracts/DefaultAccount.sol @@ -139,7 +139,6 @@ contract DefaultAccount is IAccount { bytes calldata data = _transaction.data; uint32 gas = Utils.safeCastToU32(gasleft()); - // TODO: if possible, maybe implement some way to avoid memory copying here. if ((_transaction.reserved[1] != 0) && (to == address(0))) { // Note, that createEVM can only be called with "isSystem" flag. SystemContractsCaller.systemCallWithPropagatedRevert( diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index dde42c188..b1846761f 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -294,8 +294,20 @@ object "EvmEmulator" { isStatic := iszero(iszero(and(isStatic, 0x04))) } + function fetchFromSystemContract(to, argSize) -> res { + let success := staticcall(gas(), to, 0, argSize, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + returndatacopy(0, 0, 32) + res := mload(0) + } + function isAddrEmpty(addr) -> isEmpty { - isEmpty := 0 + // We treat constructing EraVM contracts as non-existing if iszero(extcodesize(addr)) { // YUL doesn't have short-circuit evaluation if iszero(balance(addr)) { if iszero(getRawNonce(addr)) { @@ -305,33 +317,25 @@ object "EvmEmulator" { } } + // returns minNonce + 2^128 * deployment nonce. function getRawNonce(addr) -> nonce { + // selector for function getRawNonce(address _address) mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) mstore(4, addr) - - let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 0) - - if iszero(result) { - revert(0, 0) - } - - returndatacopy(0, 0, 32) - nonce := mload(0) + nonce := fetchFromSystemContract(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) } function _getRawCodeHash(account) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) + hash := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) + } - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - returndatacopy(0, 0, 32) - hash := mload(0) + function _isEVM(_addr) -> isEVM { + // function isAccountEVM(address _addr) external view returns (bool); + mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) + mstore(4, _addr) + isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } // Basically performs an extcodecopy, while returning the length of the bytecode. @@ -344,17 +348,8 @@ object "EvmEmulator" { 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) + // The first word of returndata is the true length of the bytecode + codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) if gt(_len, codeLen) { _len := codeLen @@ -437,10 +432,7 @@ object "EvmEmulator" { } } - function performSystemCall( - to, - dataLength, - ) { + function performSystemCall(to, dataLength) { let success := performSystemCallRevertable(to, dataLength) if iszero(success) { @@ -449,15 +441,12 @@ object "EvmEmulator" { } } - function performSystemCallRevertable( - to, - dataLength, - ) -> success { + function performSystemCallRevertable(to, dataLength) -> success { let farCallAbi := shl(248, 1) // system call // dataOffset is 0 // dataStart is 0 farCallAbi := or(farCallAbi, shl(96, dataLength)) - farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + farCallAbi := or(farCallAbi, shl(192, gas())) // shardId is 0 // forwardingMode is 0 // not constructor call @@ -465,35 +454,12 @@ object "EvmEmulator" { success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } - function _isEVM(_addr) -> isEVM { - // function isAccountEVM(address _addr) external view returns (bool); - mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) - mstore(4, _addr) - - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - returndatacopy(0, 0, 32) - isEVM := mload(0) - } - - function zkVmGasToEvmGas(_zkevmGas) -> calczkevmGas { - calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) // TODO round up - } - function getEvmGasFromContext() -> evmGas { - let _gas := gas() - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) // TODO CHECK GAS MECHANICS + // Caller must pass at least OVERHEAD() ergs + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) - switch lt(_gas, requiredGas) - case 1 { - evmGas := 0 - } - default { + let _gas := gas() + if gt(_gas, requiredGas) { evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) } } @@ -847,11 +813,11 @@ object "EvmEmulator" { switch _isEVM(addr) case 0 { // zkEVM native - let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) + let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas let zkEvmGasBefore := gas() success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() - let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) + let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) if gt(gasToPass, gasUsed) { frameGasLeft := sub(gasToPass, gasUsed) // TODO check @@ -871,11 +837,11 @@ object "EvmEmulator" { switch _isEVM(addr) case 0 { // zkEVM native - let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) + let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas let zkEvmGasBefore := gas() success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() - let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) + let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) if gt(gasToPass, gasUsed) { frameGasLeft := sub(gasToPass, gasUsed) // TODO check @@ -888,17 +854,29 @@ object "EvmEmulator" { } } - function _getZkEVMGasForCall(_evmGas, addr) -> zkevmGas { - // TODO CHECK COSTS CALCULATION - zkevmGas := mul(_evmGas, GAS_DIVISOR()) + function calcUsedEvmGasByZkVmCall(zkEvmGasBefore) -> evmGasUsed { + let zkevmGasUsed := sub(zkEvmGasBefore, gas()) // caller should guarantee correctness + // should not overflow, VM can't pass more than u32 of gas + evmGasUsed := div(add(zkevmGasUsed, sub(GAS_DIVISOR(), 1)), GAS_DIVISOR()) // rounding up + } + + function calcZkVmGasForCall(evmGasToPass, addr) -> zkevmGas { + zkevmGas := mul(evmGasToPass, GAS_DIVISOR()) + + // charge for contract decommitment 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(add(byteSize, 31), 32), // rounding up + DECOMMIT_COST_PER_WORD() + ) + + if gt(decommitGasCost, zkevmGas) { + zkevmGas := 0 } - let decommitGasCost := mul(div(byteSize,32), DECOMMIT_COST_PER_WORD()) + zkevmGas := sub(zkevmGas, decommitGasCost) - if gt(zkevmGas, UINT32_MAX()) { + + if gt(zkevmGas, UINT32_MAX()) { // Should never happen zkevmGas := UINT32_MAX() } } @@ -979,15 +957,11 @@ object "EvmEmulator" { function _saveReturndataAfterZkEVMCall() { loadReturndataIntoActivePtr() - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - - mstore(lastRtSzOffset, returndatasize()) + mstore(LAST_RETURNDATA_SIZE_OFFSET(), returndatasize()) } function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft { - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() let rtsz := returndatasize() - loadReturndataIntoActivePtr() // if (rtsz > 31) @@ -1007,7 +981,7 @@ object "EvmEmulator" { case 0 { returndatacopy(_outputOffset, 32, _outputLen) } default { returndatacopy(_outputOffset, 32, sub(rtsz, 32)) } - mstore(lastRtSzOffset, sub(rtsz, 32)) + mstore(LAST_RETURNDATA_SIZE_OFFSET(), sub(rtsz, 32)) // Skip the returnData ptrAddIntoActive(32) @@ -1015,11 +989,9 @@ object "EvmEmulator" { } function _eraseReturndataPointer() { - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - let activePtrSize := getActivePtrDataSize() ptrShrinkIntoActive(and(activePtrSize, 0xFFFFFFFF))// uint32(activePtrSize) - mstore(lastRtSzOffset, 0) + mstore(LAST_RETURNDATA_SIZE_OFFSET(), 0) } //////////////////////////////////////////////////////////////// @@ -1157,16 +1129,12 @@ object "EvmEmulator" { } } - function performSystemCallForCreate( - value, - bytecodeStart, - bytecodeLen, - ) -> success { + function performSystemCallForCreate(value, bytecodeStart, bytecodeLen) -> success { let farCallAbi := shl(248, 1) // system call // dataOffset is 0 farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) - farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + farCallAbi := or(farCallAbi, shl(192, gas())) // shardId is 0 // forwardingMode is 0 // not constructor call (ContractDeployer will call constructor) @@ -1182,16 +1150,7 @@ object "EvmEmulator" { function _fetchConstructorReturnGas() -> gasLeft { mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - - let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - returndatacopy(0, 0, 32) - gasLeft := mload(0) + gasLeft := fetchFromSystemContract(DEPLOYER_SYSTEM_CONTRACT(), 4) } //////////////////////////////////////////////////////////////// @@ -3311,8 +3270,20 @@ object "EvmEmulator" { isStatic := iszero(iszero(and(isStatic, 0x04))) } + function fetchFromSystemContract(to, argSize) -> res { + let success := staticcall(gas(), to, 0, argSize, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + returndatacopy(0, 0, 32) + res := mload(0) + } + function isAddrEmpty(addr) -> isEmpty { - isEmpty := 0 + // We treat constructing EraVM contracts as non-existing if iszero(extcodesize(addr)) { // YUL doesn't have short-circuit evaluation if iszero(balance(addr)) { if iszero(getRawNonce(addr)) { @@ -3322,33 +3293,25 @@ object "EvmEmulator" { } } + // returns minNonce + 2^128 * deployment nonce. function getRawNonce(addr) -> nonce { + // selector for function getRawNonce(address _address) mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) mstore(4, addr) - - let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 0) - - if iszero(result) { - revert(0, 0) - } - - returndatacopy(0, 0, 32) - nonce := mload(0) + nonce := fetchFromSystemContract(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) } function _getRawCodeHash(account) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) + hash := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) + } - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - returndatacopy(0, 0, 32) - hash := mload(0) + function _isEVM(_addr) -> isEVM { + // function isAccountEVM(address _addr) external view returns (bool); + mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) + mstore(4, _addr) + isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } // Basically performs an extcodecopy, while returning the length of the bytecode. @@ -3361,17 +3324,8 @@ object "EvmEmulator" { 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) + // The first word of returndata is the true length of the bytecode + codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) if gt(_len, codeLen) { _len := codeLen @@ -3454,10 +3408,7 @@ object "EvmEmulator" { } } - function performSystemCall( - to, - dataLength, - ) { + function performSystemCall(to, dataLength) { let success := performSystemCallRevertable(to, dataLength) if iszero(success) { @@ -3466,15 +3417,12 @@ object "EvmEmulator" { } } - function performSystemCallRevertable( - to, - dataLength, - ) -> success { + function performSystemCallRevertable(to, dataLength) -> success { let farCallAbi := shl(248, 1) // system call // dataOffset is 0 // dataStart is 0 farCallAbi := or(farCallAbi, shl(96, dataLength)) - farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + farCallAbi := or(farCallAbi, shl(192, gas())) // shardId is 0 // forwardingMode is 0 // not constructor call @@ -3482,35 +3430,12 @@ object "EvmEmulator" { success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } - function _isEVM(_addr) -> isEVM { - // function isAccountEVM(address _addr) external view returns (bool); - mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) - mstore(4, _addr) - - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - returndatacopy(0, 0, 32) - isEVM := mload(0) - } - - function zkVmGasToEvmGas(_zkevmGas) -> calczkevmGas { - calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) // TODO round up - } - function getEvmGasFromContext() -> evmGas { - let _gas := gas() - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) // TODO CHECK GAS MECHANICS + // Caller must pass at least OVERHEAD() ergs + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) - switch lt(_gas, requiredGas) - case 1 { - evmGas := 0 - } - default { + let _gas := gas() + if gt(_gas, requiredGas) { evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) } } @@ -3864,11 +3789,11 @@ object "EvmEmulator" { switch _isEVM(addr) case 0 { // zkEVM native - let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) + let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas let zkEvmGasBefore := gas() success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() - let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) + let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) if gt(gasToPass, gasUsed) { frameGasLeft := sub(gasToPass, gasUsed) // TODO check @@ -3888,11 +3813,11 @@ object "EvmEmulator" { switch _isEVM(addr) case 0 { // zkEVM native - let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) + let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas let zkEvmGasBefore := gas() success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() - let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) + let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) if gt(gasToPass, gasUsed) { frameGasLeft := sub(gasToPass, gasUsed) // TODO check @@ -3905,17 +3830,29 @@ object "EvmEmulator" { } } - function _getZkEVMGasForCall(_evmGas, addr) -> zkevmGas { - // TODO CHECK COSTS CALCULATION - zkevmGas := mul(_evmGas, GAS_DIVISOR()) + function calcUsedEvmGasByZkVmCall(zkEvmGasBefore) -> evmGasUsed { + let zkevmGasUsed := sub(zkEvmGasBefore, gas()) // caller should guarantee correctness + // should not overflow, VM can't pass more than u32 of gas + evmGasUsed := div(add(zkevmGasUsed, sub(GAS_DIVISOR(), 1)), GAS_DIVISOR()) // rounding up + } + + function calcZkVmGasForCall(evmGasToPass, addr) -> zkevmGas { + zkevmGas := mul(evmGasToPass, GAS_DIVISOR()) + + // charge for contract decommitment 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(add(byteSize, 31), 32), // rounding up + DECOMMIT_COST_PER_WORD() + ) + + if gt(decommitGasCost, zkevmGas) { + zkevmGas := 0 } - let decommitGasCost := mul(div(byteSize,32), DECOMMIT_COST_PER_WORD()) + zkevmGas := sub(zkevmGas, decommitGasCost) - if gt(zkevmGas, UINT32_MAX()) { + + if gt(zkevmGas, UINT32_MAX()) { // Should never happen zkevmGas := UINT32_MAX() } } @@ -3996,15 +3933,11 @@ object "EvmEmulator" { function _saveReturndataAfterZkEVMCall() { loadReturndataIntoActivePtr() - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - - mstore(lastRtSzOffset, returndatasize()) + mstore(LAST_RETURNDATA_SIZE_OFFSET(), returndatasize()) } function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft { - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() let rtsz := returndatasize() - loadReturndataIntoActivePtr() // if (rtsz > 31) @@ -4024,7 +3957,7 @@ object "EvmEmulator" { case 0 { returndatacopy(_outputOffset, 32, _outputLen) } default { returndatacopy(_outputOffset, 32, sub(rtsz, 32)) } - mstore(lastRtSzOffset, sub(rtsz, 32)) + mstore(LAST_RETURNDATA_SIZE_OFFSET(), sub(rtsz, 32)) // Skip the returnData ptrAddIntoActive(32) @@ -4032,11 +3965,9 @@ object "EvmEmulator" { } function _eraseReturndataPointer() { - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - let activePtrSize := getActivePtrDataSize() ptrShrinkIntoActive(and(activePtrSize, 0xFFFFFFFF))// uint32(activePtrSize) - mstore(lastRtSzOffset, 0) + mstore(LAST_RETURNDATA_SIZE_OFFSET(), 0) } //////////////////////////////////////////////////////////////// @@ -4174,16 +4105,12 @@ object "EvmEmulator" { } } - function performSystemCallForCreate( - value, - bytecodeStart, - bytecodeLen, - ) -> success { + function performSystemCallForCreate(value, bytecodeStart, bytecodeLen) -> success { let farCallAbi := shl(248, 1) // system call // dataOffset is 0 farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) - farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + farCallAbi := or(farCallAbi, shl(192, gas())) // shardId is 0 // forwardingMode is 0 // not constructor call (ContractDeployer will call constructor) @@ -4199,16 +4126,7 @@ object "EvmEmulator" { function _fetchConstructorReturnGas() -> gasLeft { mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - - let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - returndatacopy(0, 0, 32) - gasLeft := mload(0) + gasLeft := fetchFromSystemContract(DEPLOYER_SYSTEM_CONTRACT(), 4) } //////////////////////////////////////////////////////////////// diff --git a/system-contracts/contracts/SystemContractErrors.sol b/system-contracts/contracts/SystemContractErrors.sol index 4e5b5bfbe..3f0f8c257 100644 --- a/system-contracts/contracts/SystemContractErrors.sol +++ b/system-contracts/contracts/SystemContractErrors.sol @@ -144,5 +144,6 @@ enum BytecodeError { NumberOfWords, Length, WordsMustBeOdd, - DictionaryLength + DictionaryLength, + EvmBytecodeLength } diff --git a/system-contracts/contracts/libraries/Utils.sol b/system-contracts/contracts/libraries/Utils.sol index 6ea897f28..8bcc02a4d 100644 --- a/system-contracts/contracts/libraries/Utils.sol +++ b/system-contracts/contracts/libraries/Utils.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.20; import {EfficientCall} from "./EfficientCall.sol"; import {RLPEncoder} from "./RLPEncoder.sol"; import {MalformedBytecode, BytecodeError, Overflow} from "../SystemContractErrors.sol"; +import {ERA_VM_BYTECODE_FLAG, EVM_BYTECODE_FLAG} from "../Constants.sol"; /** * @author Matter Labs @@ -45,18 +46,14 @@ library Utils { } function isCodeHashEVM(bytes32 _bytecodeHash) internal pure returns (bool) { - // TODO: use constants for that - return (uint8(_bytecodeHash[0]) == 2); + return (uint8(_bytecodeHash[0]) == EVM_BYTECODE_FLAG); } /// @return codeLength The bytecode length in bytes function bytecodeLenInBytes(bytes32 _bytecodeHash) internal pure returns (uint256 codeLength) { - // TODO: use constants for that - - if (uint8(_bytecodeHash[0]) == 1) { + if (uint8(_bytecodeHash[0]) == ERA_VM_BYTECODE_FLAG) { codeLength = bytecodeLenInWords(_bytecodeHash) << 5; // _bytecodeHash * 32 - } else if (uint8(_bytecodeHash[0]) == 2) { - // TODO: maybe rename the function + } else if (uint8(_bytecodeHash[0]) == EVM_BYTECODE_FLAG) { codeLength = bytecodeLenInWords(_bytecodeHash); } else { codeLength = 0; @@ -130,8 +127,9 @@ 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"); + if (_bytecode.length > MAX_EVM_BYTECODE_LENGTH) { + revert MalformedBytecode(BytecodeError.EvmBytecodeLength); + } hashedEVMBytecode = sha256(_bytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index b93e7dc8b..119237aa2 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -229,8 +229,20 @@ function getIsStaticFromCallFlags() -> isStatic { isStatic := iszero(iszero(and(isStatic, 0x04))) } +function fetchFromSystemContract(to, argSize) -> res { + let success := staticcall(gas(), to, 0, argSize, 0, 0) + + if iszero(success) { + // This error should never happen + revert(0, 0) + } + + returndatacopy(0, 0, 32) + res := mload(0) +} + function isAddrEmpty(addr) -> isEmpty { - isEmpty := 0 + // We treat constructing EraVM contracts as non-existing if iszero(extcodesize(addr)) { // YUL doesn't have short-circuit evaluation if iszero(balance(addr)) { if iszero(getRawNonce(addr)) { @@ -240,33 +252,25 @@ function isAddrEmpty(addr) -> isEmpty { } } +// returns minNonce + 2^128 * deployment nonce. function getRawNonce(addr) -> nonce { + // selector for function getRawNonce(address _address) mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) mstore(4, addr) - - let result := staticcall(gas(), NONCE_HOLDER_SYSTEM_CONTRACT(), 0, 36, 0, 0) - - if iszero(result) { - revert(0, 0) - } - - returndatacopy(0, 0, 32) - nonce := mload(0) + nonce := fetchFromSystemContract(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) } function _getRawCodeHash(account) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) + hash := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) +} - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - returndatacopy(0, 0, 32) - hash := mload(0) +function _isEVM(_addr) -> isEVM { + // function isAccountEVM(address _addr) external view returns (bool); + mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) + mstore(4, _addr) + isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } // Basically performs an extcodecopy, while returning the length of the bytecode. @@ -279,17 +283,8 @@ 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) + // The first word of returndata is the true length of the bytecode + codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) if gt(_len, codeLen) { _len := codeLen @@ -372,10 +367,7 @@ function expandMemory(offset, size) -> gasCost { } } -function performSystemCall( - to, - dataLength, -) { +function performSystemCall(to, dataLength) { let success := performSystemCallRevertable(to, dataLength) if iszero(success) { @@ -384,15 +376,12 @@ function performSystemCall( } } -function performSystemCallRevertable( - to, - dataLength, -) -> success { +function performSystemCallRevertable(to, dataLength) -> success { let farCallAbi := shl(248, 1) // system call // dataOffset is 0 // dataStart is 0 farCallAbi := or(farCallAbi, shl(96, dataLength)) - farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + farCallAbi := or(farCallAbi, shl(192, gas())) // shardId is 0 // forwardingMode is 0 // not constructor call @@ -400,35 +389,12 @@ function performSystemCallRevertable( success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } -function _isEVM(_addr) -> isEVM { - // function isAccountEVM(address _addr) external view returns (bool); - mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) - mstore(4, _addr) - - let success := staticcall(gas(), ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 0, 36, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - returndatacopy(0, 0, 32) - isEVM := mload(0) -} - -function zkVmGasToEvmGas(_zkevmGas) -> calczkevmGas { - calczkevmGas := div(_zkevmGas, GAS_DIVISOR()) // TODO round up -} - function getEvmGasFromContext() -> evmGas { - let _gas := gas() - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) // TODO CHECK GAS MECHANICS + // Caller must pass at least OVERHEAD() ergs + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) - switch lt(_gas, requiredGas) - case 1 { - evmGas := 0 - } - default { + let _gas := gas() + if gt(_gas, requiredGas) { evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) } } @@ -782,11 +748,11 @@ function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, r switch _isEVM(addr) case 0 { // zkEVM native - let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) + let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas let zkEvmGasBefore := gas() success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() - let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) + let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) if gt(gasToPass, gasUsed) { frameGasLeft := sub(gasToPass, gasUsed) // TODO check @@ -806,11 +772,11 @@ function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, re switch _isEVM(addr) case 0 { // zkEVM native - let zkEvmGasToPass := _getZkEVMGasForCall(gasToPass, addr) + let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas let zkEvmGasBefore := gas() success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) _saveReturndataAfterZkEVMCall() - let gasUsed := zkVmGasToEvmGas(sub(zkEvmGasBefore, gas())) + let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) if gt(gasToPass, gasUsed) { frameGasLeft := sub(gasToPass, gasUsed) // TODO check @@ -823,17 +789,29 @@ function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, re } } -function _getZkEVMGasForCall(_evmGas, addr) -> zkevmGas { - // TODO CHECK COSTS CALCULATION - zkevmGas := mul(_evmGas, GAS_DIVISOR()) +function calcUsedEvmGasByZkVmCall(zkEvmGasBefore) -> evmGasUsed { + let zkevmGasUsed := sub(zkEvmGasBefore, gas()) // caller should guarantee correctness + // should not overflow, VM can't pass more than u32 of gas + evmGasUsed := div(add(zkevmGasUsed, sub(GAS_DIVISOR(), 1)), GAS_DIVISOR()) // rounding up +} + +function calcZkVmGasForCall(evmGasToPass, addr) -> zkevmGas { + zkevmGas := mul(evmGasToPass, GAS_DIVISOR()) + + // charge for contract decommitment 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(add(byteSize, 31), 32), // rounding up + DECOMMIT_COST_PER_WORD() + ) + + if gt(decommitGasCost, zkevmGas) { + zkevmGas := 0 } - let decommitGasCost := mul(div(byteSize,32), DECOMMIT_COST_PER_WORD()) + zkevmGas := sub(zkevmGas, decommitGasCost) - if gt(zkevmGas, UINT32_MAX()) { + + if gt(zkevmGas, UINT32_MAX()) { // Should never happen zkevmGas := UINT32_MAX() } } @@ -914,15 +892,11 @@ function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { function _saveReturndataAfterZkEVMCall() { loadReturndataIntoActivePtr() - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - - mstore(lastRtSzOffset, returndatasize()) + mstore(LAST_RETURNDATA_SIZE_OFFSET(), returndatasize()) } function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft { - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() let rtsz := returndatasize() - loadReturndataIntoActivePtr() // if (rtsz > 31) @@ -942,7 +916,7 @@ function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft { case 0 { returndatacopy(_outputOffset, 32, _outputLen) } default { returndatacopy(_outputOffset, 32, sub(rtsz, 32)) } - mstore(lastRtSzOffset, sub(rtsz, 32)) + mstore(LAST_RETURNDATA_SIZE_OFFSET(), sub(rtsz, 32)) // Skip the returnData ptrAddIntoActive(32) @@ -950,11 +924,9 @@ function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft { } function _eraseReturndataPointer() { - let lastRtSzOffset := LAST_RETURNDATA_SIZE_OFFSET() - let activePtrSize := getActivePtrDataSize() ptrShrinkIntoActive(and(activePtrSize, 0xFFFFFFFF))// uint32(activePtrSize) - mstore(lastRtSzOffset, 0) + mstore(LAST_RETURNDATA_SIZE_OFFSET(), 0) } //////////////////////////////////////////////////////////////// @@ -1092,16 +1064,12 @@ function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> } } -function performSystemCallForCreate( - value, - bytecodeStart, - bytecodeLen, -) -> success { +function performSystemCallForCreate(value, bytecodeStart, bytecodeLen) -> success { let farCallAbi := shl(248, 1) // system call // dataOffset is 0 farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) - farCallAbi := or(farCallAbi, shl(192, gas())) // TODO overflow + farCallAbi := or(farCallAbi, shl(192, gas())) // shardId is 0 // forwardingMode is 0 // not constructor call (ContractDeployer will call constructor) @@ -1117,16 +1085,7 @@ function performSystemCallForCreate( function _fetchConstructorReturnGas() -> gasLeft { mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - - let success := staticcall(gas(), DEPLOYER_SYSTEM_CONTRACT(), 0, 4, 0, 0) - - if iszero(success) { - // This error should never happen - revert(0, 0) - } - - returndatacopy(0, 0, 32) - gasLeft := mload(0) + gasLeft := fetchFromSystemContract(DEPLOYER_SYSTEM_CONTRACT(), 4) } //////////////////////////////////////////////////////////////// From 488fcedf11dd454cc6238c7fe740147cbeae9049 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 27 Oct 2024 20:34:09 +0100 Subject: [PATCH 118/183] fix(EVM): Fix emulator memory layout (#1004) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 301 +++++++++--------- .../evm-emulator/EvmEmulator.template.yul | 19 +- .../EvmEmulatorFunctions.template.yul | 79 +++-- .../evm-emulator/EvmEmulatorLoop.template.yul | 62 ++-- 5 files changed, 228 insertions(+), 237 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index d595df6a6..b08b9c43c 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000bf9ff70e59cec40743babb8d27f5c9f4c93ff57e8eedb18de1e2c030791", - "sourceCodeHash": "0x4c367f9487ededd71bb93878d46cb41a3c4b1e4799ccaa9f0d76eb25ee9eec82" + "bytecodeHash": "0x01000bf951f622f0d9e094c6f9f90056b1c80f99cfae14721855d0f399820e6e", + "sourceCodeHash": "0x52bb88bbed85cff18cdb0a4f970135d055161fa9bace1d9373c3063e6d4da8a8" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index b1846761f..1414aa58f 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1,27 +1,24 @@ object "EvmEmulator" { code { function MAX_POSSIBLE_ACTIVE_BYTECODE() -> max { - max := MAX_POSSIBLE_INIT_BYTECODE() + max := MAX_POSSIBLE_INIT_BYTECODE_LEN() } /// @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() - if gt(size, MAX_POSSIBLE_INIT_BYTECODE()) { + if gt(size, MAX_POSSIBLE_INIT_BYTECODE_LEN()) { panic() } - mstore(bytecodeLengthOffset, size) + mstore(BYTECODE_LEN_OFFSET(), size) mstore(EMPTY_CODE_OFFSET(), 0) - copyActivePtrData(bytecodeOffset, 0, size) + copyActivePtrData(BYTECODE_OFFSET(), 0, size) } function padBytecode(offset, len) -> blobOffset, blobLen { @@ -48,7 +45,7 @@ object "EvmEmulator" { function validateBytecodeAndChargeGas(offset, deployedCodeLen, gasToReturn) -> returnGas { if deployedCodeLen { // EIP-3860 - if gt(deployedCodeLen, MAX_POSSIBLE_DEPLOYED_BYTECODE()) { + if gt(deployedCodeLen, MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN()) { panic() } @@ -135,16 +132,12 @@ object "EvmEmulator" { offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } - function BYTECODE_OFFSET() -> offset { + function BYTECODE_LEN_OFFSET() -> offset { offset := add(STACK_OFFSET(), mul(1024, 32)) } - function MAX_POSSIBLE_DEPLOYED_BYTECODE() -> max { - max := 24576 - } - - function MAX_POSSIBLE_INIT_BYTECODE() -> max { - max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE()) // EIP-3860 + function BYTECODE_OFFSET() -> offset { + offset := add(BYTECODE_LEN_OFFSET(), 32) } // reserved empty slot to simplify PUSH N opcodes @@ -152,22 +145,30 @@ object "EvmEmulator" { offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_ACTIVE_BYTECODE()) } - function MEM_OFFSET() -> offset { + function MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() -> max { + max := 24576 // EIP-170 + } + + function MAX_POSSIBLE_INIT_BYTECODE_LEN() -> max { + max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN()) // EIP-3860 + } + + function MEM_LEN_OFFSET() -> offset { offset := add(EMPTY_CODE_OFFSET(), 32) } - function MEM_OFFSET_INNER() -> offset { - offset := add(MEM_OFFSET(), 32) + function MEM_OFFSET() -> offset { + offset := add(MEM_LEN_OFFSET(), 32) } // Used to simplify gas calculations for memory expansion. // The cost to increase the memory to 4 MB is close to 30M gas - function MAX_POSSIBLE_MEM() -> max { + function MAX_POSSIBLE_MEM_LEN() -> max { max := 0x400000 // 4MB } function MAX_MEMORY_FRAME() -> max { - max := add(MEM_OFFSET_INNER(), MAX_POSSIBLE_MEM()) + max := add(MEM_OFFSET(), MAX_POSSIBLE_MEM_LEN()) } function MAX_UINT() -> max_uint { @@ -339,23 +340,17 @@ object "EvmEmulator" { } // 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 { + function _fetchDeployedCodeWithDest(addr, dstOffset, srcOffset, len) -> codeLen { let codeHash := _getRawCodeHash(addr) - mstore(0, codeHash) // The first word of returndata is the true length of the bytecode codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) - if gt(_len, codeLen) { - _len := codeLen + if gt(len, codeLen) { + len := codeLen } - returndatacopy(dest, add(32, _offset), _len) + returndatacopy(dstOffset, add(32, srcOffset), len) } // Returns the length of the bytecode. @@ -382,14 +377,15 @@ object "EvmEmulator" { } function getDeployedBytecode() { - let codeLen := _fetchDeployedCode( - getCodeAddress(), - add(BYTECODE_OFFSET(), 32), - MAX_POSSIBLE_DEPLOYED_BYTECODE() + let codeLen := _fetchDeployedCodeWithDest( + getCodeAddress(), + BYTECODE_OFFSET(), // destination offset + 0, // source offset + MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() ) mstore(EMPTY_CODE_OFFSET(), 0) - mstore(BYTECODE_OFFSET(), codeLen) + mstore(BYTECODE_LEN_OFFSET(), codeLen) } function getMax(a, b) -> max { @@ -404,7 +400,7 @@ object "EvmEmulator" { function expandMemory(offset, size) -> gasCost { // memory expansion costs 0 if size is 0 if size { - let oldSizeInWords := mload(MEM_OFFSET()) + let oldSizeInWords := mload(MEM_LEN_OFFSET()) // div rounding up let newSizeInWords := div(add(add(offset, size), 31), 32) @@ -427,7 +423,7 @@ object "EvmEmulator" { gasCost := add(linearPart, quadraticPart) - mstore(MEM_OFFSET(), newSizeInWords) + mstore(MEM_LEN_OFFSET(), newSizeInWords) } } } @@ -505,7 +501,7 @@ object "EvmEmulator" { } function pushStackItem(sp, item, oldStackHead) -> newSp, stackHead { - if iszero(lt(sp, BYTECODE_OFFSET())) { + if iszero(lt(sp, BYTECODE_LEN_OFFSET())) { panic() } @@ -533,7 +529,7 @@ object "EvmEmulator" { } function pushStackCheck(sp, numInputs) { - if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { + if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_LEN_OFFSET())) { panic() } } @@ -684,9 +680,9 @@ object "EvmEmulator" { addr, gasToPass, value, - add(argsOffset, MEM_OFFSET_INNER()), + add(argsOffset, MEM_OFFSET()), argsSize, - add(retOffset, MEM_OFFSET_INNER()), + add(retOffset, MEM_OFFSET()), retSize ) @@ -740,9 +736,9 @@ object "EvmEmulator" { let success, frameGasLeft := _performStaticCall( addr, gasToPass, - add(MEM_OFFSET_INNER(), argsOffset), + add(MEM_OFFSET(), argsOffset), argsSize, - add(MEM_OFFSET_INNER(), retOffset), + add(MEM_OFFSET(), retOffset), retSize ) @@ -797,13 +793,13 @@ object "EvmEmulator" { let success := delegatecall( providedErgs(), addr, - add(MEM_OFFSET_INNER(), argsOffset), + add(MEM_OFFSET(), argsOffset), argsSize, 0, 0 ) - let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET(), retOffset), retSize) newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success @@ -902,7 +898,7 @@ object "EvmEmulator" { // 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 + // Take into account MEM_OFFSET() when passing the argsOffset function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { switch addr case 0x01 { // ecRecover @@ -1023,7 +1019,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // EIP-3860 - if gt(size, MAX_POSSIBLE_INIT_BYTECODE()) { + if gt(size, MAX_POSSIBLE_INIT_BYTECODE_LEN()) { panic() } @@ -1053,7 +1049,7 @@ object "EvmEmulator" { } if iszero(err) { - offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow + offset := add(MEM_OFFSET(), offset) // caller must ensure that it doesn't overflow evmGasLeft, addr := _executeCreate(offset, size, value, evmGasLeft, isCreate2, salt) } } @@ -1202,17 +1198,17 @@ object "EvmEmulator" { isStatic, ) -> returnOffset, returnLen, retGasLeft { - returnOffset := MEM_OFFSET_INNER() + returnOffset := MEM_OFFSET() 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 ip := BYTECODE_OFFSET() let stackHead - let bytecodeEndOffset := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 32) + let bytecodeEndOffset := add(BYTECODE_OFFSET(), mload(BYTECODE_LEN_OFFSET())) for { } true { } { let opcode := readIP(ip, bytecodeEndOffset) @@ -1499,7 +1495,7 @@ object "EvmEmulator" { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - stackHead := keccak256(add(MEM_OFFSET_INNER(), offset), size) + stackHead := keccak256(add(MEM_OFFSET(), offset), size) ip := add(ip, 1) } @@ -1573,14 +1569,14 @@ object "EvmEmulator" { let dynamicGas := add(mul(3, shr(5, add(size, 31))), expandMemory(destOffset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - calldatacopy(add(destOffset, MEM_OFFSET_INNER()), offset, size) + calldatacopy(add(destOffset, MEM_OFFSET()), offset, size) ip := add(ip, 1) } case 0x38 { // OP_CODESIZE evmGasLeft := chargeGas(evmGasLeft, 2) - let bytecodeLen := mload(BYTECODE_OFFSET()) + let bytecodeLen := mload(BYTECODE_LEN_OFFSET()) sp, stackHead := pushStackItem(sp, bytecodeLen, stackHead) ip := add(ip, 1) } @@ -1602,12 +1598,12 @@ object "EvmEmulator" { let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - dstOffset := add(dstOffset, MEM_OFFSET_INNER()) - sourceOffset := add(add(sourceOffset, BYTECODE_OFFSET()), 32) + dstOffset := add(dstOffset, MEM_OFFSET()) + sourceOffset := add(sourceOffset, BYTECODE_OFFSET()) checkOverflow(sourceOffset, len) // Check bytecode overflow - if gt(add(sourceOffset, len), sub(MEM_OFFSET(), 1)) { + if gt(add(sourceOffset, len), sub(MEM_LEN_OFFSET(), 1)) { panic() } @@ -1642,20 +1638,20 @@ object "EvmEmulator" { case 0x3C { // OP_EXTCODECOPY evmGasLeft := chargeGas(evmGasLeft, 100) - let addr, dest, offset, len + let addr, dstOffset, srcOffset, len popStackCheck(sp, 4) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + srcOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(dest, len) + checkMemIsAccessible(dstOffset, len) // 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(dest, len) + expandMemory(dstOffset, len) ) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -1664,11 +1660,11 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - $llvm_AlwaysInline_llvm$_memsetToZero(dest, len) + $llvm_AlwaysInline_llvm$_memsetToZero(dstOffset, 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()))) + pop(_fetchDeployedCodeWithDest(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) } ip := add(ip, 1) @@ -1703,7 +1699,7 @@ object "EvmEmulator" { panic() } - copyActivePtrData(add(MEM_OFFSET_INNER(), dstOffset), sourceOffset, len) + copyActivePtrData(add(MEM_OFFSET(), dstOffset), sourceOffset, len) ip := add(ip, 1) } case 0x3F { // OP_EXTCODEHASH @@ -1815,7 +1811,7 @@ object "EvmEmulator" { let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - stackHead := mload(add(MEM_OFFSET_INNER(), offset)) + stackHead := mload(add(MEM_OFFSET(), offset)) ip := add(ip, 1) } @@ -1832,7 +1828,7 @@ object "EvmEmulator" { let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - mstore(add(MEM_OFFSET_INNER(), offset), value) + mstore(add(MEM_OFFSET(), offset), value) ip := add(ip, 1) } case 0x53 { // OP_MSTORE8 @@ -1848,7 +1844,7 @@ object "EvmEmulator" { let expansionGas := expandMemory(offset, 1) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - mstore8(add(MEM_OFFSET_INNER(), offset), value) + mstore8(add(MEM_OFFSET(), offset), value) ip := add(ip, 1) } case 0x54 { // OP_SLOAD @@ -1918,7 +1914,7 @@ object "EvmEmulator" { let counter counter, sp, stackHead := popStackItem(sp, stackHead) - ip := add(add(BYTECODE_OFFSET(), 32), counter) + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST let nextOpcode := readIP(ip, bytecodeEndOffset) @@ -1943,7 +1939,7 @@ object "EvmEmulator" { continue } - ip := add(add(BYTECODE_OFFSET(), 32), counter) + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST let nextOpcode := readIP(ip, bytecodeEndOffset) @@ -1960,14 +1956,14 @@ object "EvmEmulator" { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), stackHead) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_LEN_OFFSET()), 33), stackHead) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft, 2) let size - size := mload(MEM_OFFSET()) + size := mload(MEM_LEN_OFFSET()) size := shl(5, size) sp, stackHead := pushStackItem(sp, size, stackHead) ip := add(ip, 1) @@ -2020,7 +2016,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) + mcopy(add(destOffset, MEM_OFFSET()), add(offset, MEM_OFFSET()), size) ip := add(ip, 1) } case 0x5F { // OP_PUSH0 @@ -2466,7 +2462,7 @@ object "EvmEmulator" { let dynamicGas := add(shl(3, size), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - log0(add(offset, MEM_OFFSET_INNER()), size) + log0(add(offset, MEM_OFFSET()), size) ip := add(ip, 1) } case 0xA1 { // OP_LOG1 @@ -2491,7 +2487,7 @@ object "EvmEmulator" { { let topic1 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + log1(add(offset, MEM_OFFSET()), size, topic1) } ip := add(ip, 1) } @@ -2518,7 +2514,7 @@ object "EvmEmulator" { let topic1, topic2 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) + log2(add(offset, MEM_OFFSET()), size, topic1, topic2) } ip := add(ip, 1) } @@ -2546,7 +2542,7 @@ object "EvmEmulator" { topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) + log3(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3) } ip := add(ip, 1) } @@ -2575,7 +2571,7 @@ object "EvmEmulator" { topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log4(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3, topic4) + log4(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3, topic4) } ip := add(ip, 1) } @@ -2614,7 +2610,7 @@ object "EvmEmulator" { returnLen := size // Don't check overflow here since previous checks are enough to ensure this is safe - returnOffset := add(MEM_OFFSET_INNER(), offset) + returnOffset := add(MEM_OFFSET(), offset) break } case 0xF4 { // OP_DELEGATECALL @@ -2646,7 +2642,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) // Don't check overflow here since previous checks are enough to ensure this is safe - offset := add(offset, MEM_OFFSET_INNER()) + offset := add(offset, MEM_OFFSET()) if eq(isCallerEVM, 1) { offset := sub(offset, 32) @@ -3036,7 +3032,7 @@ object "EvmEmulator" { object "EvmEmulator_deployed" { code { function MAX_POSSIBLE_ACTIVE_BYTECODE() -> max { - max := MAX_POSSIBLE_DEPLOYED_BYTECODE() + max := MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() } //////////////////////////////////////////////////////////////// @@ -3111,16 +3107,12 @@ object "EvmEmulator" { offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } - function BYTECODE_OFFSET() -> offset { + function BYTECODE_LEN_OFFSET() -> offset { offset := add(STACK_OFFSET(), mul(1024, 32)) } - function MAX_POSSIBLE_DEPLOYED_BYTECODE() -> max { - max := 24576 - } - - function MAX_POSSIBLE_INIT_BYTECODE() -> max { - max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE()) // EIP-3860 + function BYTECODE_OFFSET() -> offset { + offset := add(BYTECODE_LEN_OFFSET(), 32) } // reserved empty slot to simplify PUSH N opcodes @@ -3128,22 +3120,30 @@ object "EvmEmulator" { offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_ACTIVE_BYTECODE()) } - function MEM_OFFSET() -> offset { + function MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() -> max { + max := 24576 // EIP-170 + } + + function MAX_POSSIBLE_INIT_BYTECODE_LEN() -> max { + max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN()) // EIP-3860 + } + + function MEM_LEN_OFFSET() -> offset { offset := add(EMPTY_CODE_OFFSET(), 32) } - function MEM_OFFSET_INNER() -> offset { - offset := add(MEM_OFFSET(), 32) + function MEM_OFFSET() -> offset { + offset := add(MEM_LEN_OFFSET(), 32) } // Used to simplify gas calculations for memory expansion. // The cost to increase the memory to 4 MB is close to 30M gas - function MAX_POSSIBLE_MEM() -> max { + function MAX_POSSIBLE_MEM_LEN() -> max { max := 0x400000 // 4MB } function MAX_MEMORY_FRAME() -> max { - max := add(MEM_OFFSET_INNER(), MAX_POSSIBLE_MEM()) + max := add(MEM_OFFSET(), MAX_POSSIBLE_MEM_LEN()) } function MAX_UINT() -> max_uint { @@ -3315,23 +3315,17 @@ object "EvmEmulator" { } // 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 { + function _fetchDeployedCodeWithDest(addr, dstOffset, srcOffset, len) -> codeLen { let codeHash := _getRawCodeHash(addr) - mstore(0, codeHash) // The first word of returndata is the true length of the bytecode codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) - if gt(_len, codeLen) { - _len := codeLen + if gt(len, codeLen) { + len := codeLen } - returndatacopy(dest, add(32, _offset), _len) + returndatacopy(dstOffset, add(32, srcOffset), len) } // Returns the length of the bytecode. @@ -3358,14 +3352,15 @@ object "EvmEmulator" { } function getDeployedBytecode() { - let codeLen := _fetchDeployedCode( - getCodeAddress(), - add(BYTECODE_OFFSET(), 32), - MAX_POSSIBLE_DEPLOYED_BYTECODE() + let codeLen := _fetchDeployedCodeWithDest( + getCodeAddress(), + BYTECODE_OFFSET(), // destination offset + 0, // source offset + MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() ) mstore(EMPTY_CODE_OFFSET(), 0) - mstore(BYTECODE_OFFSET(), codeLen) + mstore(BYTECODE_LEN_OFFSET(), codeLen) } function getMax(a, b) -> max { @@ -3380,7 +3375,7 @@ object "EvmEmulator" { function expandMemory(offset, size) -> gasCost { // memory expansion costs 0 if size is 0 if size { - let oldSizeInWords := mload(MEM_OFFSET()) + let oldSizeInWords := mload(MEM_LEN_OFFSET()) // div rounding up let newSizeInWords := div(add(add(offset, size), 31), 32) @@ -3403,7 +3398,7 @@ object "EvmEmulator" { gasCost := add(linearPart, quadraticPart) - mstore(MEM_OFFSET(), newSizeInWords) + mstore(MEM_LEN_OFFSET(), newSizeInWords) } } } @@ -3481,7 +3476,7 @@ object "EvmEmulator" { } function pushStackItem(sp, item, oldStackHead) -> newSp, stackHead { - if iszero(lt(sp, BYTECODE_OFFSET())) { + if iszero(lt(sp, BYTECODE_LEN_OFFSET())) { panic() } @@ -3509,7 +3504,7 @@ object "EvmEmulator" { } function pushStackCheck(sp, numInputs) { - if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { + if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_LEN_OFFSET())) { panic() } } @@ -3660,9 +3655,9 @@ object "EvmEmulator" { addr, gasToPass, value, - add(argsOffset, MEM_OFFSET_INNER()), + add(argsOffset, MEM_OFFSET()), argsSize, - add(retOffset, MEM_OFFSET_INNER()), + add(retOffset, MEM_OFFSET()), retSize ) @@ -3716,9 +3711,9 @@ object "EvmEmulator" { let success, frameGasLeft := _performStaticCall( addr, gasToPass, - add(MEM_OFFSET_INNER(), argsOffset), + add(MEM_OFFSET(), argsOffset), argsSize, - add(MEM_OFFSET_INNER(), retOffset), + add(MEM_OFFSET(), retOffset), retSize ) @@ -3773,13 +3768,13 @@ object "EvmEmulator" { let success := delegatecall( providedErgs(), addr, - add(MEM_OFFSET_INNER(), argsOffset), + add(MEM_OFFSET(), argsOffset), argsSize, 0, 0 ) - let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET(), retOffset), retSize) newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success @@ -3878,7 +3873,7 @@ object "EvmEmulator" { // 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 + // Take into account MEM_OFFSET() when passing the argsOffset function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { switch addr case 0x01 { // ecRecover @@ -3999,7 +3994,7 @@ object "EvmEmulator" { checkMemIsAccessible(offset, size) // EIP-3860 - if gt(size, MAX_POSSIBLE_INIT_BYTECODE()) { + if gt(size, MAX_POSSIBLE_INIT_BYTECODE_LEN()) { panic() } @@ -4029,7 +4024,7 @@ object "EvmEmulator" { } if iszero(err) { - offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow + offset := add(MEM_OFFSET(), offset) // caller must ensure that it doesn't overflow evmGasLeft, addr := _executeCreate(offset, size, value, evmGasLeft, isCreate2, salt) } } @@ -4178,17 +4173,17 @@ object "EvmEmulator" { isStatic, ) -> returnOffset, returnLen { - returnOffset := MEM_OFFSET_INNER() + returnOffset := MEM_OFFSET() 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 ip := BYTECODE_OFFSET() let stackHead - let bytecodeEndOffset := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 32) + let bytecodeEndOffset := add(BYTECODE_OFFSET(), mload(BYTECODE_LEN_OFFSET())) for { } true { } { let opcode := readIP(ip, bytecodeEndOffset) @@ -4475,7 +4470,7 @@ object "EvmEmulator" { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - stackHead := keccak256(add(MEM_OFFSET_INNER(), offset), size) + stackHead := keccak256(add(MEM_OFFSET(), offset), size) ip := add(ip, 1) } @@ -4549,14 +4544,14 @@ object "EvmEmulator" { let dynamicGas := add(mul(3, shr(5, add(size, 31))), expandMemory(destOffset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - calldatacopy(add(destOffset, MEM_OFFSET_INNER()), offset, size) + calldatacopy(add(destOffset, MEM_OFFSET()), offset, size) ip := add(ip, 1) } case 0x38 { // OP_CODESIZE evmGasLeft := chargeGas(evmGasLeft, 2) - let bytecodeLen := mload(BYTECODE_OFFSET()) + let bytecodeLen := mload(BYTECODE_LEN_OFFSET()) sp, stackHead := pushStackItem(sp, bytecodeLen, stackHead) ip := add(ip, 1) } @@ -4578,12 +4573,12 @@ object "EvmEmulator" { let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - dstOffset := add(dstOffset, MEM_OFFSET_INNER()) - sourceOffset := add(add(sourceOffset, BYTECODE_OFFSET()), 32) + dstOffset := add(dstOffset, MEM_OFFSET()) + sourceOffset := add(sourceOffset, BYTECODE_OFFSET()) checkOverflow(sourceOffset, len) // Check bytecode overflow - if gt(add(sourceOffset, len), sub(MEM_OFFSET(), 1)) { + if gt(add(sourceOffset, len), sub(MEM_LEN_OFFSET(), 1)) { panic() } @@ -4618,20 +4613,20 @@ object "EvmEmulator" { case 0x3C { // OP_EXTCODECOPY evmGasLeft := chargeGas(evmGasLeft, 100) - let addr, dest, offset, len + let addr, dstOffset, srcOffset, len popStackCheck(sp, 4) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + srcOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(dest, len) + checkMemIsAccessible(dstOffset, len) // 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(dest, len) + expandMemory(dstOffset, len) ) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -4640,11 +4635,11 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - $llvm_AlwaysInline_llvm$_memsetToZero(dest, len) + $llvm_AlwaysInline_llvm$_memsetToZero(dstOffset, 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()))) + pop(_fetchDeployedCodeWithDest(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) } ip := add(ip, 1) @@ -4679,7 +4674,7 @@ object "EvmEmulator" { panic() } - copyActivePtrData(add(MEM_OFFSET_INNER(), dstOffset), sourceOffset, len) + copyActivePtrData(add(MEM_OFFSET(), dstOffset), sourceOffset, len) ip := add(ip, 1) } case 0x3F { // OP_EXTCODEHASH @@ -4791,7 +4786,7 @@ object "EvmEmulator" { let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - stackHead := mload(add(MEM_OFFSET_INNER(), offset)) + stackHead := mload(add(MEM_OFFSET(), offset)) ip := add(ip, 1) } @@ -4808,7 +4803,7 @@ object "EvmEmulator" { let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - mstore(add(MEM_OFFSET_INNER(), offset), value) + mstore(add(MEM_OFFSET(), offset), value) ip := add(ip, 1) } case 0x53 { // OP_MSTORE8 @@ -4824,7 +4819,7 @@ object "EvmEmulator" { let expansionGas := expandMemory(offset, 1) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - mstore8(add(MEM_OFFSET_INNER(), offset), value) + mstore8(add(MEM_OFFSET(), offset), value) ip := add(ip, 1) } case 0x54 { // OP_SLOAD @@ -4894,7 +4889,7 @@ object "EvmEmulator" { let counter counter, sp, stackHead := popStackItem(sp, stackHead) - ip := add(add(BYTECODE_OFFSET(), 32), counter) + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST let nextOpcode := readIP(ip, bytecodeEndOffset) @@ -4919,7 +4914,7 @@ object "EvmEmulator" { continue } - ip := add(add(BYTECODE_OFFSET(), 32), counter) + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST let nextOpcode := readIP(ip, bytecodeEndOffset) @@ -4936,14 +4931,14 @@ object "EvmEmulator" { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), stackHead) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_LEN_OFFSET()), 33), stackHead) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft, 2) let size - size := mload(MEM_OFFSET()) + size := mload(MEM_LEN_OFFSET()) size := shl(5, size) sp, stackHead := pushStackItem(sp, size, stackHead) ip := add(ip, 1) @@ -4996,7 +4991,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) + mcopy(add(destOffset, MEM_OFFSET()), add(offset, MEM_OFFSET()), size) ip := add(ip, 1) } case 0x5F { // OP_PUSH0 @@ -5442,7 +5437,7 @@ object "EvmEmulator" { let dynamicGas := add(shl(3, size), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - log0(add(offset, MEM_OFFSET_INNER()), size) + log0(add(offset, MEM_OFFSET()), size) ip := add(ip, 1) } case 0xA1 { // OP_LOG1 @@ -5467,7 +5462,7 @@ object "EvmEmulator" { { let topic1 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + log1(add(offset, MEM_OFFSET()), size, topic1) } ip := add(ip, 1) } @@ -5494,7 +5489,7 @@ object "EvmEmulator" { let topic1, topic2 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) + log2(add(offset, MEM_OFFSET()), size, topic1, topic2) } ip := add(ip, 1) } @@ -5522,7 +5517,7 @@ object "EvmEmulator" { topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) + log3(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3) } ip := add(ip, 1) } @@ -5551,7 +5546,7 @@ object "EvmEmulator" { topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log4(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3, topic4) + log4(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3, topic4) } ip := add(ip, 1) } @@ -5590,7 +5585,7 @@ object "EvmEmulator" { returnLen := size // Don't check overflow here since previous checks are enough to ensure this is safe - returnOffset := add(MEM_OFFSET_INNER(), offset) + returnOffset := add(MEM_OFFSET(), offset) break } case 0xF4 { // OP_DELEGATECALL @@ -5622,7 +5617,7 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) // Don't check overflow here since previous checks are enough to ensure this is safe - offset := add(offset, MEM_OFFSET_INNER()) + offset := add(offset, MEM_OFFSET()) if eq(isCallerEVM, 1) { offset := sub(offset, 32) diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index db7499ec3..875c4b293 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -1,27 +1,24 @@ object "EvmEmulator" { code { function MAX_POSSIBLE_ACTIVE_BYTECODE() -> max { - max := MAX_POSSIBLE_INIT_BYTECODE() + max := MAX_POSSIBLE_INIT_BYTECODE_LEN() } /// @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() - if gt(size, MAX_POSSIBLE_INIT_BYTECODE()) { + if gt(size, MAX_POSSIBLE_INIT_BYTECODE_LEN()) { panic() } - mstore(bytecodeLengthOffset, size) + mstore(BYTECODE_LEN_OFFSET(), size) mstore(EMPTY_CODE_OFFSET(), 0) - copyActivePtrData(bytecodeOffset, 0, size) + copyActivePtrData(BYTECODE_OFFSET(), 0, size) } function padBytecode(offset, len) -> blobOffset, blobLen { @@ -48,7 +45,7 @@ object "EvmEmulator" { function validateBytecodeAndChargeGas(offset, deployedCodeLen, gasToReturn) -> returnGas { if deployedCodeLen { // EIP-3860 - if gt(deployedCodeLen, MAX_POSSIBLE_DEPLOYED_BYTECODE()) { + if gt(deployedCodeLen, MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN()) { panic() } @@ -71,7 +68,7 @@ object "EvmEmulator" { isStatic, ) -> returnOffset, returnLen, retGasLeft { - returnOffset := MEM_OFFSET_INNER() + returnOffset := MEM_OFFSET() returnLen := 0 @@ -110,7 +107,7 @@ object "EvmEmulator" { object "EvmEmulator_deployed" { code { function MAX_POSSIBLE_ACTIVE_BYTECODE() -> max { - max := MAX_POSSIBLE_DEPLOYED_BYTECODE() + max := MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() } @@ -121,7 +118,7 @@ object "EvmEmulator" { isStatic, ) -> returnOffset, returnLen { - returnOffset := MEM_OFFSET_INNER() + returnOffset := MEM_OFFSET() returnLen := 0 diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 119237aa2..f7f877a68 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -70,16 +70,12 @@ function STACK_OFFSET() -> offset { offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } -function BYTECODE_OFFSET() -> offset { +function BYTECODE_LEN_OFFSET() -> offset { offset := add(STACK_OFFSET(), mul(1024, 32)) } -function MAX_POSSIBLE_DEPLOYED_BYTECODE() -> max { - max := 24576 -} - -function MAX_POSSIBLE_INIT_BYTECODE() -> max { - max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE()) // EIP-3860 +function BYTECODE_OFFSET() -> offset { + offset := add(BYTECODE_LEN_OFFSET(), 32) } // reserved empty slot to simplify PUSH N opcodes @@ -87,22 +83,30 @@ function EMPTY_CODE_OFFSET() -> offset { offset := add(BYTECODE_OFFSET(), MAX_POSSIBLE_ACTIVE_BYTECODE()) } -function MEM_OFFSET() -> offset { +function MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() -> max { + max := 24576 // EIP-170 +} + +function MAX_POSSIBLE_INIT_BYTECODE_LEN() -> max { + max := mul(2, MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN()) // EIP-3860 +} + +function MEM_LEN_OFFSET() -> offset { offset := add(EMPTY_CODE_OFFSET(), 32) } -function MEM_OFFSET_INNER() -> offset { - offset := add(MEM_OFFSET(), 32) +function MEM_OFFSET() -> offset { + offset := add(MEM_LEN_OFFSET(), 32) } // Used to simplify gas calculations for memory expansion. // The cost to increase the memory to 4 MB is close to 30M gas -function MAX_POSSIBLE_MEM() -> max { +function MAX_POSSIBLE_MEM_LEN() -> max { max := 0x400000 // 4MB } function MAX_MEMORY_FRAME() -> max { - max := add(MEM_OFFSET_INNER(), MAX_POSSIBLE_MEM()) + max := add(MEM_OFFSET(), MAX_POSSIBLE_MEM_LEN()) } function MAX_UINT() -> max_uint { @@ -274,23 +278,17 @@ function _isEVM(_addr) -> isEVM { } // 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 { +function _fetchDeployedCodeWithDest(addr, dstOffset, srcOffset, len) -> codeLen { let codeHash := _getRawCodeHash(addr) - mstore(0, codeHash) // The first word of returndata is the true length of the bytecode codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) - if gt(_len, codeLen) { - _len := codeLen + if gt(len, codeLen) { + len := codeLen } - returndatacopy(dest, add(32, _offset), _len) + returndatacopy(dstOffset, add(32, srcOffset), len) } // Returns the length of the bytecode. @@ -317,14 +315,15 @@ function _fetchDeployedCodeLen(addr) -> codeLen { } function getDeployedBytecode() { - let codeLen := _fetchDeployedCode( - getCodeAddress(), - add(BYTECODE_OFFSET(), 32), - MAX_POSSIBLE_DEPLOYED_BYTECODE() + let codeLen := _fetchDeployedCodeWithDest( + getCodeAddress(), + BYTECODE_OFFSET(), // destination offset + 0, // source offset + MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() ) mstore(EMPTY_CODE_OFFSET(), 0) - mstore(BYTECODE_OFFSET(), codeLen) + mstore(BYTECODE_LEN_OFFSET(), codeLen) } function getMax(a, b) -> max { @@ -339,7 +338,7 @@ function getMax(a, b) -> max { function expandMemory(offset, size) -> gasCost { // memory expansion costs 0 if size is 0 if size { - let oldSizeInWords := mload(MEM_OFFSET()) + let oldSizeInWords := mload(MEM_LEN_OFFSET()) // div rounding up let newSizeInWords := div(add(add(offset, size), 31), 32) @@ -362,7 +361,7 @@ function expandMemory(offset, size) -> gasCost { gasCost := add(linearPart, quadraticPart) - mstore(MEM_OFFSET(), newSizeInWords) + mstore(MEM_LEN_OFFSET(), newSizeInWords) } } } @@ -440,7 +439,7 @@ function popStackItem(sp, oldStackHead) -> a, newSp, stackHead { } function pushStackItem(sp, item, oldStackHead) -> newSp, stackHead { - if iszero(lt(sp, BYTECODE_OFFSET())) { + if iszero(lt(sp, BYTECODE_LEN_OFFSET())) { panic() } @@ -468,7 +467,7 @@ function popStackCheck(sp, numInputs) { } function pushStackCheck(sp, numInputs) { - if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_OFFSET())) { + if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_LEN_OFFSET())) { panic() } } @@ -619,9 +618,9 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe addr, gasToPass, value, - add(argsOffset, MEM_OFFSET_INNER()), + add(argsOffset, MEM_OFFSET()), argsSize, - add(retOffset, MEM_OFFSET_INNER()), + add(retOffset, MEM_OFFSET()), retSize ) @@ -675,9 +674,9 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s let success, frameGasLeft := _performStaticCall( addr, gasToPass, - add(MEM_OFFSET_INNER(), argsOffset), + add(MEM_OFFSET(), argsOffset), argsSize, - add(MEM_OFFSET_INNER(), retOffset), + add(MEM_OFFSET(), retOffset), retSize ) @@ -732,13 +731,13 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGa let success := delegatecall( providedErgs(), addr, - add(MEM_OFFSET_INNER(), argsOffset), + add(MEM_OFFSET(), argsOffset), argsSize, 0, 0 ) - let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET_INNER(), retOffset), retSize) + let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET(), retOffset), retSize) newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success @@ -837,7 +836,7 @@ function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> // 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 +// Take into account MEM_OFFSET() when passing the argsOffset function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { switch addr case 0x01 { // ecRecover @@ -958,7 +957,7 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, checkMemIsAccessible(offset, size) // EIP-3860 - if gt(size, MAX_POSSIBLE_INIT_BYTECODE()) { + if gt(size, MAX_POSSIBLE_INIT_BYTECODE_LEN()) { panic() } @@ -988,7 +987,7 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, } if iszero(err) { - offset := add(MEM_OFFSET_INNER(), offset) // caller must ensure that it doesn't overflow + offset := add(MEM_OFFSET(), offset) // caller must ensure that it doesn't overflow evmGasLeft, addr := _executeCreate(offset, size, value, evmGasLeft, isCreate2, salt) } } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 22efdd53f..021872460 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -2,10 +2,10 @@ 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 ip := BYTECODE_OFFSET() let stackHead -let bytecodeEndOffset := add(add(BYTECODE_OFFSET(), mload(BYTECODE_OFFSET())), 32) +let bytecodeEndOffset := add(BYTECODE_OFFSET(), mload(BYTECODE_LEN_OFFSET())) for { } true { } { let opcode := readIP(ip, bytecodeEndOffset) @@ -292,7 +292,7 @@ for { } true { } { let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - stackHead := keccak256(add(MEM_OFFSET_INNER(), offset), size) + stackHead := keccak256(add(MEM_OFFSET(), offset), size) ip := add(ip, 1) } @@ -366,14 +366,14 @@ for { } true { } { let dynamicGas := add(mul(3, shr(5, add(size, 31))), expandMemory(destOffset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - calldatacopy(add(destOffset, MEM_OFFSET_INNER()), offset, size) + calldatacopy(add(destOffset, MEM_OFFSET()), offset, size) ip := add(ip, 1) } case 0x38 { // OP_CODESIZE evmGasLeft := chargeGas(evmGasLeft, 2) - let bytecodeLen := mload(BYTECODE_OFFSET()) + let bytecodeLen := mload(BYTECODE_LEN_OFFSET()) sp, stackHead := pushStackItem(sp, bytecodeLen, stackHead) ip := add(ip, 1) } @@ -395,12 +395,12 @@ for { } true { } { let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - dstOffset := add(dstOffset, MEM_OFFSET_INNER()) - sourceOffset := add(add(sourceOffset, BYTECODE_OFFSET()), 32) + dstOffset := add(dstOffset, MEM_OFFSET()) + sourceOffset := add(sourceOffset, BYTECODE_OFFSET()) checkOverflow(sourceOffset, len) // Check bytecode overflow - if gt(add(sourceOffset, len), sub(MEM_OFFSET(), 1)) { + if gt(add(sourceOffset, len), sub(MEM_LEN_OFFSET(), 1)) { panic() } @@ -435,20 +435,20 @@ for { } true { } { case 0x3C { // OP_EXTCODECOPY evmGasLeft := chargeGas(evmGasLeft, 100) - let addr, dest, offset, len + let addr, dstOffset, srcOffset, len popStackCheck(sp, 4) addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - dest, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + srcOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(dest, len) + checkMemIsAccessible(dstOffset, len) // 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(dest, len) + expandMemory(dstOffset, len) ) if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { @@ -457,11 +457,11 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - $llvm_AlwaysInline_llvm$_memsetToZero(dest, len) + $llvm_AlwaysInline_llvm$_memsetToZero(dstOffset, 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()))) + pop(_fetchDeployedCodeWithDest(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) } ip := add(ip, 1) @@ -496,7 +496,7 @@ for { } true { } { panic() } - copyActivePtrData(add(MEM_OFFSET_INNER(), dstOffset), sourceOffset, len) + copyActivePtrData(add(MEM_OFFSET(), dstOffset), sourceOffset, len) ip := add(ip, 1) } case 0x3F { // OP_EXTCODEHASH @@ -608,7 +608,7 @@ for { } true { } { let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - stackHead := mload(add(MEM_OFFSET_INNER(), offset)) + stackHead := mload(add(MEM_OFFSET(), offset)) ip := add(ip, 1) } @@ -625,7 +625,7 @@ for { } true { } { let expansionGas := expandMemory(offset, 32) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - mstore(add(MEM_OFFSET_INNER(), offset), value) + mstore(add(MEM_OFFSET(), offset), value) ip := add(ip, 1) } case 0x53 { // OP_MSTORE8 @@ -641,7 +641,7 @@ for { } true { } { let expansionGas := expandMemory(offset, 1) evmGasLeft := chargeGas(evmGasLeft, expansionGas) - mstore8(add(MEM_OFFSET_INNER(), offset), value) + mstore8(add(MEM_OFFSET(), offset), value) ip := add(ip, 1) } case 0x54 { // OP_SLOAD @@ -711,7 +711,7 @@ for { } true { } { let counter counter, sp, stackHead := popStackItem(sp, stackHead) - ip := add(add(BYTECODE_OFFSET(), 32), counter) + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST let nextOpcode := readIP(ip, bytecodeEndOffset) @@ -736,7 +736,7 @@ for { } true { } { continue } - ip := add(add(BYTECODE_OFFSET(), 32), counter) + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST let nextOpcode := readIP(ip, bytecodeEndOffset) @@ -753,14 +753,14 @@ for { } true { } { ip := add(ip, 1) // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_OFFSET()), 33), stackHead) + sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_LEN_OFFSET()), 33), stackHead) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft, 2) let size - size := mload(MEM_OFFSET()) + size := mload(MEM_LEN_OFFSET()) size := shl(5, size) sp, stackHead := pushStackItem(sp, size, stackHead) ip := add(ip, 1) @@ -813,7 +813,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - mcopy(add(destOffset, MEM_OFFSET_INNER()), add(offset, MEM_OFFSET_INNER()), size) + mcopy(add(destOffset, MEM_OFFSET()), add(offset, MEM_OFFSET()), size) ip := add(ip, 1) } case 0x5F { // OP_PUSH0 @@ -1259,7 +1259,7 @@ for { } true { } { let dynamicGas := add(shl(3, size), expandMemory(offset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - log0(add(offset, MEM_OFFSET_INNER()), size) + log0(add(offset, MEM_OFFSET()), size) ip := add(ip, 1) } case 0xA1 { // OP_LOG1 @@ -1284,7 +1284,7 @@ for { } true { } { { let topic1 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log1(add(offset, MEM_OFFSET_INNER()), size, topic1) + log1(add(offset, MEM_OFFSET()), size, topic1) } ip := add(ip, 1) } @@ -1311,7 +1311,7 @@ for { } true { } { let topic1, topic2 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log2(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2) + log2(add(offset, MEM_OFFSET()), size, topic1, topic2) } ip := add(ip, 1) } @@ -1339,7 +1339,7 @@ for { } true { } { topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log3(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3) + log3(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3) } ip := add(ip, 1) } @@ -1368,7 +1368,7 @@ for { } true { } { topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log4(add(offset, MEM_OFFSET_INNER()), size, topic1, topic2, topic3, topic4) + log4(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3, topic4) } ip := add(ip, 1) } @@ -1407,7 +1407,7 @@ for { } true { } { returnLen := size // Don't check overflow here since previous checks are enough to ensure this is safe - returnOffset := add(MEM_OFFSET_INNER(), offset) + returnOffset := add(MEM_OFFSET(), offset) break } case 0xF4 { // OP_DELEGATECALL @@ -1439,7 +1439,7 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) // Don't check overflow here since previous checks are enough to ensure this is safe - offset := add(offset, MEM_OFFSET_INNER()) + offset := add(offset, MEM_OFFSET()) if eq(isCallerEVM, 1) { offset := sub(offset, 32) From b631015f5f294271e96b5d34350eea6997f3c9e7 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 27 Oct 2024 21:27:28 +0100 Subject: [PATCH 119/183] Chore(EVM): Cleanup (#1027) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 310 +++++++++--------- .../evm-emulator/EvmEmulator.template.yul | 12 + .../EvmEmulatorFunctions.template.yul | 141 ++++---- .../evm-emulator/EvmEmulatorLoop.template.yul | 8 +- 5 files changed, 230 insertions(+), 245 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index b08b9c43c..e92f49154 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000bf951f622f0d9e094c6f9f90056b1c80f99cfae14721855d0f399820e6e", - "sourceCodeHash": "0x52bb88bbed85cff18cdb0a4f970135d055161fa9bace1d9373c3063e6d4da8a8" + "bytecodeHash": "0x01000bf970a938a8dfbb9f3a6dba4e34b890171371810c84934526c7638bae93", + "sourceCodeHash": "0xf72db9750c1efeb16cbb9a85f4ab793e96931ca1331b17a8376aa2b42615f23d" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 1414aa58f..2f50353f5 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -209,7 +209,7 @@ object "EvmEmulator" { revert(0, 32) } - function panic() { + function panic() { // revert consuming all EVM gas mstore(0, 0) revert(0, 32) } @@ -227,6 +227,16 @@ object "EvmEmulator" { gasRemaining := sub(prevGas, toCharge) } + function getEvmGasFromContext() -> evmGas { + // Caller must pass at least OVERHEAD() ergs + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) + + let _gas := gas() + if gt(_gas, requiredGas) { + evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) + } + } + function providedErgs() -> ergs { let _gas := gas() if gt(_gas, EVM_GAS_STIPEND()) { @@ -234,6 +244,39 @@ object "EvmEmulator" { } } + // 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(offset, size) -> gasCost { + // memory expansion costs 0 if size is 0 + if size { + let oldSizeInWords := mload(MEM_LEN_OFFSET()) + + // div rounding up + let newSizeInWords := div(add(add(offset, size), 31), 32) + + // memory_size_word = (memory_byte_size + 31) / 32 + // memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word) + // memory_expansion_cost = new_memory_cost - last_memory_cost + if gt(newSizeInWords, oldSizeInWords) { + let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords)) + let quadraticPart := sub( + div( + mul(newSizeInWords, newSizeInWords), + 512 + ), + div( + mul(oldSizeInWords, oldSizeInWords), + 512 + ) + ) + + gasCost := add(linearPart, quadraticPart) + + mstore(MEM_LEN_OFFSET(), newSizeInWords) + } + } + } + function checkMemIsAccessible(index, offset) { checkOverflow(index, offset) @@ -326,13 +369,13 @@ object "EvmEmulator" { nonce := fetchFromSystemContract(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) } - function _getRawCodeHash(account) -> hash { + function getRawCodeHash(account) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) hash := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } - function _isEVM(_addr) -> isEVM { + function isEvmContract(_addr) -> isEVM { // function isAccountEVM(address _addr) external view returns (bool); mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) mstore(4, _addr) @@ -340,8 +383,8 @@ object "EvmEmulator" { } // Basically performs an extcodecopy, while returning the length of the bytecode. - function _fetchDeployedCodeWithDest(addr, dstOffset, srcOffset, len) -> codeLen { - let codeHash := _getRawCodeHash(addr) + function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> codeLen { + let codeHash := getRawCodeHash(addr) mstore(0, codeHash) // The first word of returndata is the true length of the bytecode codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) @@ -353,10 +396,9 @@ object "EvmEmulator" { returndatacopy(dstOffset, add(32, srcOffset), len) } - // Returns the length of the bytecode. - function _fetchDeployedCodeLen(addr) -> codeLen { - let codeHash := _getRawCodeHash(addr) - + // Returns the length of the EVM bytecode. + function fetchDeployedEvmCodeLen(addr) -> codeLen { + let codeHash := getRawCodeHash(addr) mstore(0, codeHash) let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) @@ -376,18 +418,6 @@ object "EvmEmulator" { } } - function getDeployedBytecode() { - let codeLen := _fetchDeployedCodeWithDest( - getCodeAddress(), - BYTECODE_OFFSET(), // destination offset - 0, // source offset - MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() - ) - - mstore(EMPTY_CODE_OFFSET(), 0) - mstore(BYTECODE_LEN_OFFSET(), codeLen) - } - function getMax(a, b) -> max { max := b if gt(a, b) { @@ -395,39 +425,6 @@ object "EvmEmulator" { } } - // 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(offset, size) -> gasCost { - // memory expansion costs 0 if size is 0 - if size { - let oldSizeInWords := mload(MEM_LEN_OFFSET()) - - // div rounding up - let newSizeInWords := div(add(add(offset, size), 31), 32) - - // memory_size_word = (memory_byte_size + 31) / 32 - // memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word) - // memory_expansion_cost = new_memory_cost - last_memory_cost - if gt(newSizeInWords, oldSizeInWords) { - let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords)) - let quadraticPart := sub( - div( - mul(newSizeInWords, newSizeInWords), - 512 - ), - div( - mul(oldSizeInWords, oldSizeInWords), - 512 - ) - ) - - gasCost := add(linearPart, quadraticPart) - - mstore(MEM_LEN_OFFSET(), newSizeInWords) - } - } - } - function performSystemCall(to, dataLength) { let success := performSystemCallRevertable(to, dataLength) @@ -450,16 +447,6 @@ object "EvmEmulator" { success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } - function getEvmGasFromContext() -> evmGas { - // Caller must pass at least OVERHEAD() ergs - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) - - let _gas := gas() - if gt(_gas, requiredGas) { - evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) - } - } - //////////////////////////////////////////////////////////////// // STACK OPERATIONS //////////////////////////////////////////////////////////////// @@ -563,7 +550,7 @@ object "EvmEmulator" { // non-standard selector 0x01 mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) mstore(1, key) - + // should be call since we use TSTORE in gas manager let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) if iszero(success) { @@ -576,11 +563,11 @@ object "EvmEmulator" { } } - function warmSlot(key,currentValue) -> isWarm, originalValue { + function warmSlot(key, currentValue) -> isWarm, originalValue { // non-standard selector 0x02 mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) mstore(1, key) - mstore(33,currentValue) + mstore(33, currentValue) performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) @@ -591,11 +578,11 @@ object "EvmEmulator" { } } - function _pushEVMFrame(_passGas, _isStatic) { + function pushEvmFrame(passGas, isStatic) { // function pushEVMFrame // non-standard selector 0x03 - mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) - mstore(32, _passGas) + mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, isStatic)) + mstore(32, passGas) performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) } @@ -782,14 +769,14 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, gasUsed) // it is not possible to delegatecall precompiles - if iszero(_isEVM(addr)) { + if iszero(isEvmContract(addr)) { revertWithGas(evmGasLeft) } gasToPass := capGasForCall(evmGasLeft, gasToPass) evmGasLeft := sub(evmGasLeft, gasToPass) - _pushEVMFrame(gasToPass, isStatic) + pushEvmFrame(gasToPass, isStatic) let success := delegatecall( providedErgs(), addr, @@ -806,7 +793,7 @@ object "EvmEmulator" { } function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch _isEVM(addr) + switch isEvmContract(addr) case 0 { // zkEVM native let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas @@ -820,7 +807,7 @@ object "EvmEmulator" { } } default { - _pushEVMFrame(gasToPass, false) + pushEvmFrame(gasToPass, false) // VM will add EVM_GAS_STIPEND() to gas for this call // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract // so we need to add some gas for MsgValueSimulator @@ -830,7 +817,7 @@ object "EvmEmulator" { } function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch _isEVM(addr) + switch isEvmContract(addr) case 0 { // zkEVM native let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas @@ -844,7 +831,7 @@ object "EvmEmulator" { } } default { - _pushEVMFrame(gasToPass, true) + pushEvmFrame(gasToPass, true) success := staticcall(providedErgs(), addr, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } @@ -1086,7 +1073,7 @@ object "EvmEmulator" { // so even if constructor reverts, nonce stays incremented and addr stays warm // verification of the correctness of the deployed bytecode and payment of gas for its storage will occur in the frame of the new contract - _pushEVMFrame(gasForTheCall, false) + pushEvmFrame(gasForTheCall, false) // move needed memory slots to the scratch space mstore(mul(10, 32), mload(sub(offset, 0x80)) @@ -1629,9 +1616,9 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - switch _isEVM(addr) + switch isEvmContract(addr) case 0 { stackHead := extcodesize(addr) } - default { stackHead := _fetchDeployedCodeLen(addr) } + default { stackHead := fetchDeployedEvmCodeLen(addr) } ip := add(ip, 1) } @@ -1663,8 +1650,8 @@ object "EvmEmulator" { $llvm_AlwaysInline_llvm$_memsetToZero(dstOffset, len) // Gets the code from the addr - if and(iszero(iszero(_getRawCodeHash(addr))), gt(len, 0)) { - pop(_fetchDeployedCodeWithDest(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) + if and(iszero(iszero(getRawCodeHash(addr))), gt(len, 0)) { + pop(fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) } ip := add(ip, 1) @@ -3035,6 +3022,18 @@ object "EvmEmulator" { max := MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() } + function getDeployedBytecode() { + let codeLen := fetchDeployedCode( + getCodeAddress(), + BYTECODE_OFFSET(), // destination offset + 0, // source offset + MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() + ) + + mstore(EMPTY_CODE_OFFSET(), 0) + mstore(BYTECODE_LEN_OFFSET(), codeLen) + } + //////////////////////////////////////////////////////////////// // CONSTANTS //////////////////////////////////////////////////////////////// @@ -3184,7 +3183,7 @@ object "EvmEmulator" { revert(0, 32) } - function panic() { + function panic() { // revert consuming all EVM gas mstore(0, 0) revert(0, 32) } @@ -3202,6 +3201,16 @@ object "EvmEmulator" { gasRemaining := sub(prevGas, toCharge) } + function getEvmGasFromContext() -> evmGas { + // Caller must pass at least OVERHEAD() ergs + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) + + let _gas := gas() + if gt(_gas, requiredGas) { + evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) + } + } + function providedErgs() -> ergs { let _gas := gas() if gt(_gas, EVM_GAS_STIPEND()) { @@ -3209,6 +3218,39 @@ object "EvmEmulator" { } } + // 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(offset, size) -> gasCost { + // memory expansion costs 0 if size is 0 + if size { + let oldSizeInWords := mload(MEM_LEN_OFFSET()) + + // div rounding up + let newSizeInWords := div(add(add(offset, size), 31), 32) + + // memory_size_word = (memory_byte_size + 31) / 32 + // memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word) + // memory_expansion_cost = new_memory_cost - last_memory_cost + if gt(newSizeInWords, oldSizeInWords) { + let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords)) + let quadraticPart := sub( + div( + mul(newSizeInWords, newSizeInWords), + 512 + ), + div( + mul(oldSizeInWords, oldSizeInWords), + 512 + ) + ) + + gasCost := add(linearPart, quadraticPart) + + mstore(MEM_LEN_OFFSET(), newSizeInWords) + } + } + } + function checkMemIsAccessible(index, offset) { checkOverflow(index, offset) @@ -3301,13 +3343,13 @@ object "EvmEmulator" { nonce := fetchFromSystemContract(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) } - function _getRawCodeHash(account) -> hash { + function getRawCodeHash(account) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) hash := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } - function _isEVM(_addr) -> isEVM { + function isEvmContract(_addr) -> isEVM { // function isAccountEVM(address _addr) external view returns (bool); mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) mstore(4, _addr) @@ -3315,8 +3357,8 @@ object "EvmEmulator" { } // Basically performs an extcodecopy, while returning the length of the bytecode. - function _fetchDeployedCodeWithDest(addr, dstOffset, srcOffset, len) -> codeLen { - let codeHash := _getRawCodeHash(addr) + function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> codeLen { + let codeHash := getRawCodeHash(addr) mstore(0, codeHash) // The first word of returndata is the true length of the bytecode codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) @@ -3328,10 +3370,9 @@ object "EvmEmulator" { returndatacopy(dstOffset, add(32, srcOffset), len) } - // Returns the length of the bytecode. - function _fetchDeployedCodeLen(addr) -> codeLen { - let codeHash := _getRawCodeHash(addr) - + // Returns the length of the EVM bytecode. + function fetchDeployedEvmCodeLen(addr) -> codeLen { + let codeHash := getRawCodeHash(addr) mstore(0, codeHash) let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) @@ -3351,18 +3392,6 @@ object "EvmEmulator" { } } - function getDeployedBytecode() { - let codeLen := _fetchDeployedCodeWithDest( - getCodeAddress(), - BYTECODE_OFFSET(), // destination offset - 0, // source offset - MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() - ) - - mstore(EMPTY_CODE_OFFSET(), 0) - mstore(BYTECODE_LEN_OFFSET(), codeLen) - } - function getMax(a, b) -> max { max := b if gt(a, b) { @@ -3370,39 +3399,6 @@ object "EvmEmulator" { } } - // 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(offset, size) -> gasCost { - // memory expansion costs 0 if size is 0 - if size { - let oldSizeInWords := mload(MEM_LEN_OFFSET()) - - // div rounding up - let newSizeInWords := div(add(add(offset, size), 31), 32) - - // memory_size_word = (memory_byte_size + 31) / 32 - // memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word) - // memory_expansion_cost = new_memory_cost - last_memory_cost - if gt(newSizeInWords, oldSizeInWords) { - let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords)) - let quadraticPart := sub( - div( - mul(newSizeInWords, newSizeInWords), - 512 - ), - div( - mul(oldSizeInWords, oldSizeInWords), - 512 - ) - ) - - gasCost := add(linearPart, quadraticPart) - - mstore(MEM_LEN_OFFSET(), newSizeInWords) - } - } - } - function performSystemCall(to, dataLength) { let success := performSystemCallRevertable(to, dataLength) @@ -3425,16 +3421,6 @@ object "EvmEmulator" { success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } - function getEvmGasFromContext() -> evmGas { - // Caller must pass at least OVERHEAD() ergs - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) - - let _gas := gas() - if gt(_gas, requiredGas) { - evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) - } - } - //////////////////////////////////////////////////////////////// // STACK OPERATIONS //////////////////////////////////////////////////////////////// @@ -3538,7 +3524,7 @@ object "EvmEmulator" { // non-standard selector 0x01 mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) mstore(1, key) - + // should be call since we use TSTORE in gas manager let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) if iszero(success) { @@ -3551,11 +3537,11 @@ object "EvmEmulator" { } } - function warmSlot(key,currentValue) -> isWarm, originalValue { + function warmSlot(key, currentValue) -> isWarm, originalValue { // non-standard selector 0x02 mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) mstore(1, key) - mstore(33,currentValue) + mstore(33, currentValue) performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) @@ -3566,11 +3552,11 @@ object "EvmEmulator" { } } - function _pushEVMFrame(_passGas, _isStatic) { + function pushEvmFrame(passGas, isStatic) { // function pushEVMFrame // non-standard selector 0x03 - mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) - mstore(32, _passGas) + mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, isStatic)) + mstore(32, passGas) performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) } @@ -3757,14 +3743,14 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, gasUsed) // it is not possible to delegatecall precompiles - if iszero(_isEVM(addr)) { + if iszero(isEvmContract(addr)) { revertWithGas(evmGasLeft) } gasToPass := capGasForCall(evmGasLeft, gasToPass) evmGasLeft := sub(evmGasLeft, gasToPass) - _pushEVMFrame(gasToPass, isStatic) + pushEvmFrame(gasToPass, isStatic) let success := delegatecall( providedErgs(), addr, @@ -3781,7 +3767,7 @@ object "EvmEmulator" { } function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch _isEVM(addr) + switch isEvmContract(addr) case 0 { // zkEVM native let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas @@ -3795,7 +3781,7 @@ object "EvmEmulator" { } } default { - _pushEVMFrame(gasToPass, false) + pushEvmFrame(gasToPass, false) // VM will add EVM_GAS_STIPEND() to gas for this call // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract // so we need to add some gas for MsgValueSimulator @@ -3805,7 +3791,7 @@ object "EvmEmulator" { } function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch _isEVM(addr) + switch isEvmContract(addr) case 0 { // zkEVM native let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas @@ -3819,7 +3805,7 @@ object "EvmEmulator" { } } default { - _pushEVMFrame(gasToPass, true) + pushEvmFrame(gasToPass, true) success := staticcall(providedErgs(), addr, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } @@ -4061,7 +4047,7 @@ object "EvmEmulator" { // so even if constructor reverts, nonce stays incremented and addr stays warm // verification of the correctness of the deployed bytecode and payment of gas for its storage will occur in the frame of the new contract - _pushEVMFrame(gasForTheCall, false) + pushEvmFrame(gasForTheCall, false) // move needed memory slots to the scratch space mstore(mul(10, 32), mload(sub(offset, 0x80)) @@ -4604,9 +4590,9 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - switch _isEVM(addr) + switch isEvmContract(addr) case 0 { stackHead := extcodesize(addr) } - default { stackHead := _fetchDeployedCodeLen(addr) } + default { stackHead := fetchDeployedEvmCodeLen(addr) } ip := add(ip, 1) } @@ -4638,8 +4624,8 @@ object "EvmEmulator" { $llvm_AlwaysInline_llvm$_memsetToZero(dstOffset, len) // Gets the code from the addr - if and(iszero(iszero(_getRawCodeHash(addr))), gt(len, 0)) { - pop(_fetchDeployedCodeWithDest(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) + if and(iszero(iszero(getRawCodeHash(addr))), gt(len, 0)) { + pop(fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) } ip := add(ip, 1) diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index 875c4b293..5f4c2a0dd 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -110,6 +110,18 @@ object "EvmEmulator" { max := MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() } + function getDeployedBytecode() { + let codeLen := fetchDeployedCode( + getCodeAddress(), + BYTECODE_OFFSET(), // destination offset + 0, // source offset + MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() + ) + + mstore(EMPTY_CODE_OFFSET(), 0) + mstore(BYTECODE_LEN_OFFSET(), codeLen) + } + function $llvm_NoInline_llvm$_simulate( diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index f7f877a68..804b1abae 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -147,7 +147,7 @@ function revertWithGas(evmGasLeft) { revert(0, 32) } -function panic() { +function panic() { // revert consuming all EVM gas mstore(0, 0) revert(0, 32) } @@ -165,6 +165,16 @@ function chargeGas(prevGas, toCharge) -> gasRemaining { gasRemaining := sub(prevGas, toCharge) } +function getEvmGasFromContext() -> evmGas { + // Caller must pass at least OVERHEAD() ergs + let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) + + let _gas := gas() + if gt(_gas, requiredGas) { + evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) + } +} + function providedErgs() -> ergs { let _gas := gas() if gt(_gas, EVM_GAS_STIPEND()) { @@ -172,6 +182,39 @@ function providedErgs() -> ergs { } } +// 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(offset, size) -> gasCost { + // memory expansion costs 0 if size is 0 + if size { + let oldSizeInWords := mload(MEM_LEN_OFFSET()) + + // div rounding up + let newSizeInWords := div(add(add(offset, size), 31), 32) + + // memory_size_word = (memory_byte_size + 31) / 32 + // memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word) + // memory_expansion_cost = new_memory_cost - last_memory_cost + if gt(newSizeInWords, oldSizeInWords) { + let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords)) + let quadraticPart := sub( + div( + mul(newSizeInWords, newSizeInWords), + 512 + ), + div( + mul(oldSizeInWords, oldSizeInWords), + 512 + ) + ) + + gasCost := add(linearPart, quadraticPart) + + mstore(MEM_LEN_OFFSET(), newSizeInWords) + } + } +} + function checkMemIsAccessible(index, offset) { checkOverflow(index, offset) @@ -264,13 +307,13 @@ function getRawNonce(addr) -> nonce { nonce := fetchFromSystemContract(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) } -function _getRawCodeHash(account) -> hash { +function getRawCodeHash(account) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) mstore(4, account) hash := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } -function _isEVM(_addr) -> isEVM { +function isEvmContract(_addr) -> isEVM { // function isAccountEVM(address _addr) external view returns (bool); mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) mstore(4, _addr) @@ -278,8 +321,8 @@ function _isEVM(_addr) -> isEVM { } // Basically performs an extcodecopy, while returning the length of the bytecode. -function _fetchDeployedCodeWithDest(addr, dstOffset, srcOffset, len) -> codeLen { - let codeHash := _getRawCodeHash(addr) +function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> codeLen { + let codeHash := getRawCodeHash(addr) mstore(0, codeHash) // The first word of returndata is the true length of the bytecode codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) @@ -291,10 +334,9 @@ function _fetchDeployedCodeWithDest(addr, dstOffset, srcOffset, len) -> codeLen returndatacopy(dstOffset, add(32, srcOffset), len) } -// Returns the length of the bytecode. -function _fetchDeployedCodeLen(addr) -> codeLen { - let codeHash := _getRawCodeHash(addr) - +// Returns the length of the EVM bytecode. +function fetchDeployedEvmCodeLen(addr) -> codeLen { + let codeHash := getRawCodeHash(addr) mstore(0, codeHash) let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) @@ -314,18 +356,6 @@ function _fetchDeployedCodeLen(addr) -> codeLen { } } -function getDeployedBytecode() { - let codeLen := _fetchDeployedCodeWithDest( - getCodeAddress(), - BYTECODE_OFFSET(), // destination offset - 0, // source offset - MAX_POSSIBLE_DEPLOYED_BYTECODE_LEN() - ) - - mstore(EMPTY_CODE_OFFSET(), 0) - mstore(BYTECODE_LEN_OFFSET(), codeLen) -} - function getMax(a, b) -> max { max := b if gt(a, b) { @@ -333,39 +363,6 @@ function getMax(a, b) -> max { } } -// 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(offset, size) -> gasCost { - // memory expansion costs 0 if size is 0 - if size { - let oldSizeInWords := mload(MEM_LEN_OFFSET()) - - // div rounding up - let newSizeInWords := div(add(add(offset, size), 31), 32) - - // memory_size_word = (memory_byte_size + 31) / 32 - // memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word) - // memory_expansion_cost = new_memory_cost - last_memory_cost - if gt(newSizeInWords, oldSizeInWords) { - let linearPart := mul(3, sub(newSizeInWords, oldSizeInWords)) - let quadraticPart := sub( - div( - mul(newSizeInWords, newSizeInWords), - 512 - ), - div( - mul(oldSizeInWords, oldSizeInWords), - 512 - ) - ) - - gasCost := add(linearPart, quadraticPart) - - mstore(MEM_LEN_OFFSET(), newSizeInWords) - } - } -} - function performSystemCall(to, dataLength) { let success := performSystemCallRevertable(to, dataLength) @@ -388,16 +385,6 @@ function performSystemCallRevertable(to, dataLength) -> success { success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } -function getEvmGasFromContext() -> evmGas { - // Caller must pass at least OVERHEAD() ergs - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) - - let _gas := gas() - if gt(_gas, requiredGas) { - evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) - } -} - //////////////////////////////////////////////////////////////// // STACK OPERATIONS //////////////////////////////////////////////////////////////// @@ -501,7 +488,7 @@ function isSlotWarm(key) -> isWarm { // non-standard selector 0x01 mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) mstore(1, key) - + // should be call since we use TSTORE in gas manager let success := call(gas(), EVM_GAS_MANAGER_CONTRACT(), 0, 0, 33, 0, 0) if iszero(success) { @@ -514,11 +501,11 @@ function isSlotWarm(key) -> isWarm { } } -function warmSlot(key,currentValue) -> isWarm, originalValue { +function warmSlot(key, currentValue) -> isWarm, originalValue { // non-standard selector 0x02 mstore(0, 0x0200000000000000000000000000000000000000000000000000000000000000) mstore(1, key) - mstore(33,currentValue) + mstore(33, currentValue) performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) @@ -529,11 +516,11 @@ function warmSlot(key,currentValue) -> isWarm, originalValue { } } -function _pushEVMFrame(_passGas, _isStatic) { +function pushEvmFrame(passGas, isStatic) { // function pushEVMFrame // non-standard selector 0x03 - mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, _isStatic)) - mstore(32, _passGas) + mstore(0, or(0x0300000000000000000000000000000000000000000000000000000000000000, isStatic)) + mstore(32, passGas) performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 64) } @@ -720,14 +707,14 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGa evmGasLeft := chargeGas(evmGasLeft, gasUsed) // it is not possible to delegatecall precompiles - if iszero(_isEVM(addr)) { + if iszero(isEvmContract(addr)) { revertWithGas(evmGasLeft) } gasToPass := capGasForCall(evmGasLeft, gasToPass) evmGasLeft := sub(evmGasLeft, gasToPass) - _pushEVMFrame(gasToPass, isStatic) + pushEvmFrame(gasToPass, isStatic) let success := delegatecall( providedErgs(), addr, @@ -744,7 +731,7 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGa } function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch _isEVM(addr) + switch isEvmContract(addr) case 0 { // zkEVM native let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas @@ -758,7 +745,7 @@ function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, r } } default { - _pushEVMFrame(gasToPass, false) + pushEvmFrame(gasToPass, false) // VM will add EVM_GAS_STIPEND() to gas for this call // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract // so we need to add some gas for MsgValueSimulator @@ -768,7 +755,7 @@ function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, r } function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch _isEVM(addr) + switch isEvmContract(addr) case 0 { // zkEVM native let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas @@ -782,7 +769,7 @@ function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, re } } default { - _pushEVMFrame(gasToPass, true) + pushEvmFrame(gasToPass, true) success := staticcall(providedErgs(), addr, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } @@ -1024,7 +1011,7 @@ function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> // so even if constructor reverts, nonce stays incremented and addr stays warm // verification of the correctness of the deployed bytecode and payment of gas for its storage will occur in the frame of the new contract - _pushEVMFrame(gasForTheCall, false) + pushEvmFrame(gasForTheCall, false) // move needed memory slots to the scratch space mstore(mul(10, 32), mload(sub(offset, 0x80)) diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 021872460..9288d63a7 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -426,9 +426,9 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 2500) } - switch _isEVM(addr) + switch isEvmContract(addr) case 0 { stackHead := extcodesize(addr) } - default { stackHead := _fetchDeployedCodeLen(addr) } + default { stackHead := fetchDeployedEvmCodeLen(addr) } ip := add(ip, 1) } @@ -460,8 +460,8 @@ for { } true { } { $llvm_AlwaysInline_llvm$_memsetToZero(dstOffset, len) // Gets the code from the addr - if and(iszero(iszero(_getRawCodeHash(addr))), gt(len, 0)) { - pop(_fetchDeployedCodeWithDest(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) + if and(iszero(iszero(getRawCodeHash(addr))), gt(len, 0)) { + pop(fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) } ip := add(ip, 1) From 0ae124acc15701b23207026d06d2284d501e2370 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 27 Oct 2024 21:56:23 +0100 Subject: [PATCH 120/183] fix(EVM): Fx SSTORE gas model (#1028) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 96 ++++++++++--------- .../evm-emulator/EvmEmulatorLoop.template.yul | 49 +++++----- system-contracts/package.json | 2 +- 4 files changed, 83 insertions(+), 68 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index e92f49154..068095eb1 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000bf970a938a8dfbb9f3a6dba4e34b890171371810c84934526c7638bae93", - "sourceCodeHash": "0xf72db9750c1efeb16cbb9a85f4ab793e96931ca1331b17a8376aa2b42615f23d" + "bytecodeHash": "0x01000bfd321f885d5af9cc5734faa0025e0b3337af9e92dd56fb8db127d55310", + "sourceCodeHash": "0x1c63fcedca37868e5cf4c6ad40629da7f52acf042be38efb5aa14b2d05ce7a36" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 2f50353f5..095f9d036 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1854,43 +1854,48 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0x55 { // OP_SSTORE - evmGasLeft := chargeGas(evmGasLeft, 100) - if isStatic { panic() } - let key, value, gasSpent + if lt(evmGasLeft, 2301) { // if <= 2300 + panic() + } + + let key, value popStackCheck(sp, 2) key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) 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); // TODO - let currentValue := sload(key) - let wasWarm, originalValue := warmSlot(key, currentValue) - if eq(value, currentValue) { - continue - } + let dynamicGas := 100 + // 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. + let currentValue := sload(key) + let wasWarm, originalValue := warmSlot(key, currentValue) - if eq(originalValue, currentValue) { - gasSpent := 19900 - if originalValue { - gasSpent := 2800 - } - } + if iszero(wasWarm) { + dynamicGas := add(dynamicGas, 2100) + } - if iszero(wasWarm) { - gasSpent := add(gasSpent, 2100) + if eq(value, currentValue) { // no-op + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + continue + } + + if eq(originalValue, currentValue) { + switch originalValue + case 0 { + dynamicGas := add(dynamicGas, 19900) + } + default { + dynamicGas := add(dynamicGas, 2800) } } - evmGasLeft := chargeGas(evmGasLeft, gasSpent) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) sstore(key, value) } // NOTE: We don't currently do full jumpdest validation @@ -4828,43 +4833,48 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0x55 { // OP_SSTORE - evmGasLeft := chargeGas(evmGasLeft, 100) - if isStatic { panic() } - let key, value, gasSpent + if lt(evmGasLeft, 2301) { // if <= 2300 + panic() + } + + let key, value popStackCheck(sp, 2) key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) 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); // TODO - 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 - } - } + let dynamicGas := 100 + // 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. + let currentValue := sload(key) + let wasWarm, originalValue := warmSlot(key, currentValue) + + if iszero(wasWarm) { + dynamicGas := add(dynamicGas, 2100) + } - if iszero(wasWarm) { - gasSpent := add(gasSpent, 2100) + if eq(value, currentValue) { // no-op + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + continue + } + + if eq(originalValue, currentValue) { + switch originalValue + case 0 { + dynamicGas := add(dynamicGas, 19900) + } + default { + dynamicGas := add(dynamicGas, 2800) } } - evmGasLeft := chargeGas(evmGasLeft, gasSpent) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) sstore(key, value) } // NOTE: We don't currently do full jumpdest validation diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 9288d63a7..d37e8b4f8 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -664,43 +664,48 @@ for { } true { } { ip := add(ip, 1) } case 0x55 { // OP_SSTORE - evmGasLeft := chargeGas(evmGasLeft, 100) - if isStatic { panic() } - let key, value, gasSpent + if lt(evmGasLeft, 2301) { // if <= 2300 + panic() + } + + let key, value popStackCheck(sp, 2) key, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) 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); // TODO - 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 - } - } + let dynamicGas := 100 + // 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. + let currentValue := sload(key) + let wasWarm, originalValue := warmSlot(key, currentValue) - if iszero(wasWarm) { - gasSpent := add(gasSpent, 2100) + if iszero(wasWarm) { + dynamicGas := add(dynamicGas, 2100) + } + + if eq(value, currentValue) { // no-op + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + continue + } + + if eq(originalValue, currentValue) { + switch originalValue + case 0 { + dynamicGas := add(dynamicGas, 19900) + } + default { + dynamicGas := add(dynamicGas, 2800) } } - evmGasLeft := chargeGas(evmGasLeft, gasSpent) + evmGasLeft := chargeGas(evmGasLeft, dynamicGas) sstore(key, value) } // NOTE: We don't currently do full jumpdest validation diff --git a/system-contracts/package.json b/system-contracts/package.json index 27b5ee5e3..085dab5d2 100644 --- a/system-contracts/package.json +++ b/system-contracts/package.json @@ -52,7 +52,7 @@ "scripts": { "build": "yarn build:system-contracts && yarn build:bootloader", "build:bootloader": "yarn preprocess:bootloader && yarn compile-yul compile-bootloader", - "build:system-contracts": "yarn preprocess:system-contracts && hardhat compile && yarn compile-yul compile-precompiles", + "build:system-contracts": "yarn preprocess:emulator && yarn preprocess:system-contracts && hardhat compile && yarn compile-yul compile-precompiles", "build:test-system-contracts": "yarn preprocess:system-contracts --test-mode && hardhat compile && yarn compile-yul compile-precompiles && yarn compile-zasm", "calculate-hashes:check": "ts-node scripts/calculate-hashes.ts --check-only", "calculate-hashes:fix": "ts-node scripts/calculate-hashes.ts", From a40ebe117a4b6a2ec7b30b4980fec9bca9522288 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 27 Oct 2024 22:35:18 +0100 Subject: [PATCH 121/183] feat(EVM): Optimize EXTCODEHASH (#1029) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 56 ++++++++++++++----- .../EvmEmulatorFunctions.template.yul | 18 ++++-- .../evm-emulator/EvmEmulatorLoop.template.yul | 10 +++- 4 files changed, 65 insertions(+), 23 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 068095eb1..b7febc5b0 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000bfd321f885d5af9cc5734faa0025e0b3337af9e92dd56fb8db127d55310", - "sourceCodeHash": "0x1c63fcedca37868e5cf4c6ad40629da7f52acf042be38efb5aa14b2d05ce7a36" + "bytecodeHash": "0x01000c17a11dbdb15973a96a4ddd5b95f19843ea7e7affa8f63fe0e5e4ef5b7c", + "sourceCodeHash": "0x5b6098d09a93c5a55cc119d6a30a6e8e446db778af4a4350deb1b5d8ba5c764a" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 095f9d036..b14bcaf04 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -363,22 +363,28 @@ object "EvmEmulator" { // returns minNonce + 2^128 * deployment nonce. function getRawNonce(addr) -> nonce { - // selector for function getRawNonce(address _address) + // selector for function getRawNonce(address addr) mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) mstore(4, addr) nonce := fetchFromSystemContract(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) } - function getRawCodeHash(account) -> hash { + function getRawCodeHash(addr) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) - mstore(4, account) + mstore(4, addr) hash := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } - function isEvmContract(_addr) -> isEVM { - // function isAccountEVM(address _addr) external view returns (bool); + function getEvmExtcodehash(addr) -> evmCodeHash { + mstore(0, 0x54A3314700000000000000000000000000000000000000000000000000000000) + mstore(4, addr) + evmCodeHash := fetchFromSystemContract(DEPLOYER_SYSTEM_CONTRACT(), 36) + } + + function isEvmContract(addr) -> isEVM { + // function isAccountEVM(address addr) external view returns (bool); mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) - mstore(4, _addr) + mstore(4, addr) isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } @@ -1704,7 +1710,15 @@ object "EvmEmulator" { stackHead := 0 continue } - stackHead := extcodehash(addr) + + switch isEvmContract(addr) + case 0 { + stackHead := extcodehash(addr) + } + default { + stackHead := getEvmExtcodehash(addr) + } + } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) @@ -3342,22 +3356,28 @@ object "EvmEmulator" { // returns minNonce + 2^128 * deployment nonce. function getRawNonce(addr) -> nonce { - // selector for function getRawNonce(address _address) + // selector for function getRawNonce(address addr) mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) mstore(4, addr) nonce := fetchFromSystemContract(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) } - function getRawCodeHash(account) -> hash { + function getRawCodeHash(addr) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) - mstore(4, account) + mstore(4, addr) hash := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } - function isEvmContract(_addr) -> isEVM { - // function isAccountEVM(address _addr) external view returns (bool); + function getEvmExtcodehash(addr) -> evmCodeHash { + mstore(0, 0x54A3314700000000000000000000000000000000000000000000000000000000) + mstore(4, addr) + evmCodeHash := fetchFromSystemContract(DEPLOYER_SYSTEM_CONTRACT(), 36) + } + + function isEvmContract(addr) -> isEVM { + // function isAccountEVM(address addr) external view returns (bool); mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) - mstore(4, _addr) + mstore(4, addr) isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } @@ -4683,7 +4703,15 @@ object "EvmEmulator" { stackHead := 0 continue } - stackHead := extcodehash(addr) + + switch isEvmContract(addr) + case 0 { + stackHead := extcodehash(addr) + } + default { + stackHead := getEvmExtcodehash(addr) + } + } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 804b1abae..81c7fe614 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -301,22 +301,28 @@ function isAddrEmpty(addr) -> isEmpty { // returns minNonce + 2^128 * deployment nonce. function getRawNonce(addr) -> nonce { - // selector for function getRawNonce(address _address) + // selector for function getRawNonce(address addr) mstore(0, 0x5AA9B6B500000000000000000000000000000000000000000000000000000000) mstore(4, addr) nonce := fetchFromSystemContract(NONCE_HOLDER_SYSTEM_CONTRACT(), 36) } -function getRawCodeHash(account) -> hash { +function getRawCodeHash(addr) -> hash { mstore(0, 0x4DE2E46800000000000000000000000000000000000000000000000000000000) - mstore(4, account) + mstore(4, addr) hash := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } -function isEvmContract(_addr) -> isEVM { - // function isAccountEVM(address _addr) external view returns (bool); +function getEvmExtcodehash(addr) -> evmCodeHash { + mstore(0, 0x54A3314700000000000000000000000000000000000000000000000000000000) + mstore(4, addr) + evmCodeHash := fetchFromSystemContract(DEPLOYER_SYSTEM_CONTRACT(), 36) +} + +function isEvmContract(addr) -> isEVM { + // function isAccountEVM(address addr) external view returns (bool); mstore(0, 0x8C04047700000000000000000000000000000000000000000000000000000000) - mstore(4, _addr) + mstore(4, addr) isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index d37e8b4f8..89fbd1504 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -514,7 +514,15 @@ for { } true { } { stackHead := 0 continue } - stackHead := extcodehash(addr) + + switch isEvmContract(addr) + case 0 { + stackHead := extcodehash(addr) + } + default { + stackHead := getEvmExtcodehash(addr) + } + } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) From bb4443dd99bcb86ed31d68d2a66b19712bf208ba Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 27 Oct 2024 23:07:53 +0100 Subject: [PATCH 122/183] fix(EVM): Fix TODOs in KnownCodesStorage (#1030) --- system-contracts/SystemContractsHashes.json | 32 +++++++++---------- .../contracts/KnownCodesStorage.sol | 10 ++---- .../contracts/libraries/Utils.sol | 28 +++++++++++++--- 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index b7febc5b0..c0fdc0010 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": "0x010000777c28746231003a691b8bb0f9b223ab03a3c411e43b1aaa8027436826", + "bytecodeHash": "0x0100007717dc02746f2cb709926f52fd61d96cb46101936b1185de956b574682", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f1b8097e1e177edecd7df3d65dbb8f8139b4c457cffc733bdef0773868", + "bytecodeHash": "0x010006f13cbea31bcb77c670158b426d21e8f580951a7fc4ef9b2212ab67a30f", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004727ddd19b221a109fd0719aa01ecb7de4268b6ed14dfd0b45bcc55139", + "bytecodeHash": "0x010000470f54c0e5cc35e659aefce4a345fde4a905a3396e08e6e08e9502c4a2", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013fffa9e5ba3f487cd7443293b210b09d15e8a7f77f6e11f677edc9e835", + "bytecodeHash": "0x0100013fc97f375809db1ce6fb6e5951a6a2e52361002d148a1768eaf6bad9e7", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010006992c48504c10c9acb66b6e847fcd2328389a0d2334fb174f981ba5b291", + "bytecodeHash": "0x01000699eff3447b6d51bb1eaf32037bd4aafbbb1baa9a70f76125830ee97937", "sourceCodeHash": "0x9ad8797aa39ae899362ed936542fe13160ef2a2ed95d67c2d66ac62077e61059" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003ff3ab2e8e975033d54d64a171cf58c793146ebfba6fd04ce302674373", + "bytecodeHash": "0x0100003f8b2f60eb000b89fd840c27aec320d8df5e2c860b6d3bd0f6010762ec", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x01000509a98e0465c3b9f288422931c4d008f31a3f6c2aae25efd0ffb1bd58ae", + "bytecodeHash": "0x01000509cce015327bf1a00b6007b69a884240bd559faa2fa2f45bfa9e9abd96", "sourceCodeHash": "0xef448fac6b6f1c217b6495ee134a3553e02dfb920fd46bc71de33672e64d9ab8" }, { @@ -59,56 +59,56 @@ "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033808c6348792b1baecebf5840e441aff76ef6e2a1715ad2dabf4f90f9", + "bytecodeHash": "0x01000033536138bb4d3541b826f736392db784f4d1f419b8f98edbdf9ec99b05", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000bb4c0f108c511d5ff44054b6a961561647f1cc1f6db1eb97eaab5580e4", - "sourceCodeHash": "0xeb83e3a2ea2f50b93122363b8dd56fbcfe821d11723d849eecbde3d6af1147de" + "bytecodeHash": "0x010000cd5b164d338301040c3f5a2c73c775b2e0f7b7c5049dc2198d912e8d95", + "sourceCodeHash": "0x851fb5e170dfde39f1f9bc74654ec0b8f8f1d4c2fb20c06c77844c1e3ee0659a" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000265ad11b9309608bde6568a778510ac188b1c2db1a7119a2ebc74f76c9b", + "bytecodeHash": "0x01000265b0203371672d9ba8d5f4ae92635606bf9c77b550c387917bddb9acdf", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f339b1e3862bac3fa7045aa87ada897107fef091436f1ea508c8761835", + "bytecodeHash": "0x010000f36487ed4282e33a1f8a323586e769a33409c55ddccb1d839117bfbe9c", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x01000059d44bf38d8f50b1c01be8ee1354ff38d3a787235e12701ce82a6a00b8", + "bytecodeHash": "0x0100005946d91043ea599c05aa4d735d401d7aa6600b5b12f967c6ec8c983fb7", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cf5c0b2f62856538d58d994976fa069acf385235b7d13e42708f99c475", + "bytecodeHash": "0x010000cf9366b12f1aed3bf74174fbca6eb1a6ab841830659a527408c11d3a32", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x010000415057478c53ab74234e8f205d80e935a96f2341c8c72da2ac422b0222", + "bytecodeHash": "0x01000041d59901297fd33c6a872493d201611711ab0e5a44ba4c24f4671756b2", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c508dcad8f1823f20e91164ff035d6077172b188f3d4c840e4fd8e8d88", + "bytecodeHash": "0x010001c5238dcdd879430a91bf5ce05aa4f2d57ef5044b5e460a45bb426267fd", "sourceCodeHash": "0xe2f6eb015d260aafe9405b28ef3ec27921add4de7f329b7ef61e0aa6c9365e29" }, { diff --git a/system-contracts/contracts/KnownCodesStorage.sol b/system-contracts/contracts/KnownCodesStorage.sol index 0bbaeeb17..1f3755e4e 100644 --- a/system-contracts/contracts/KnownCodesStorage.sol +++ b/system-contracts/contracts/KnownCodesStorage.sol @@ -85,19 +85,15 @@ contract KnownCodesStorage is IKnownCodesStorage, SystemContractBase { } } + /// @notice The method used by ContractDeployer to publish EVM bytecode + /// @dev Bytecode should be padded by EraVM rules + /// @param paddedBytecode The bytecode to be published function publishEVMBytecode( bytes calldata paddedBytecode ) external payable onlyCallFrom(address(DEPLOYER_SYSTEM_CONTRACT)) returns (bytes32) { - /* - TODO: ensure that it is properly padded, etc. - To preserve EVM compatibility, we can not emit any events here. - */ - - // ToDO: use efficient call bytes32 vesionedBytecodeHash = Utils.hashEVMBytecode(paddedBytecode); if (getMarker(vesionedBytecodeHash) == 0) { - // ToDO: use efficient call L1_MESSENGER_CONTRACT.sendToL1(paddedBytecode); assembly { diff --git a/system-contracts/contracts/libraries/Utils.sol b/system-contracts/contracts/libraries/Utils.sol index 8bcc02a4d..211a23d83 100644 --- a/system-contracts/contracts/libraries/Utils.sol +++ b/system-contracts/contracts/libraries/Utils.sol @@ -118,7 +118,7 @@ library Utils { EfficientCall.sha(_bytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // Setting the version of the hash - hashedBytecode = (hashedBytecode | bytes32(uint256(1 << 248))); + hashedBytecode = (hashedBytecode | bytes32(uint256(ERA_VM_BYTECODE_FLAG) << 248)); // Setting the length hashedBytecode = hashedBytecode | bytes32(lengthInWords << 224); } @@ -126,15 +126,35 @@ library Utils { // the real max supported number is 2^16, but we'll stick to evm convention uint256 internal constant MAX_EVM_BYTECODE_LENGTH = (2 ** 16) - 1; - function hashEVMBytecode(bytes memory _bytecode) internal view returns (bytes32 hashedEVMBytecode) { + /// @notice Validate the bytecode format and calculate its hash. + /// @param _bytecode The EVM bytecode to hash. + /// @return hashedEVMBytecode The 32-byte hash of the EVM bytecode. + /// Note: The function reverts the execution if the bytecode has non expected format: + /// - Bytecode bytes length is not a multiple of 32 + /// - Bytecode bytes length is greater than 2^16 - 1 bytes + /// - Bytecode words length is not odd + function hashEVMBytecode(bytes calldata _bytecode) internal view returns (bytes32 hashedEVMBytecode) { + // Note that the length of the bytecode must be provided in 32-byte words. + if (_bytecode.length % 32 != 0) { + revert MalformedBytecode(BytecodeError.Length); + } + if (_bytecode.length > MAX_EVM_BYTECODE_LENGTH) { revert MalformedBytecode(BytecodeError.EvmBytecodeLength); } - hashedEVMBytecode = sha256(_bytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + uint256 lengthInWords = _bytecode.length / 32; + // bytecode length in words must be odd + if (lengthInWords % 2 == 0) { + revert MalformedBytecode(BytecodeError.WordsMustBeOdd); + } + + hashedEVMBytecode = + EfficientCall.sha(_bytecode) & + 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // Setting the version of the hash - hashedEVMBytecode = (hashedEVMBytecode | bytes32(uint256(2 << 248))); + hashedEVMBytecode = (hashedEVMBytecode | bytes32(uint256(EVM_BYTECODE_FLAG) << 248)); hashedEVMBytecode = hashedEVMBytecode | bytes32(_bytecode.length << 224); } From 146aa346e556fa478b6205bc8d1f4fb151b697f4 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 28 Oct 2024 01:39:21 +0100 Subject: [PATCH 123/183] fix(EVM): Warm origin and sender accounts (#1036) --- system-contracts/SystemContractsHashes.json | 8 ++++---- system-contracts/contracts/EvmEmulator.yul | 6 ++++-- system-contracts/contracts/EvmGasManager.yul | 17 ++++++++++++++--- .../EvmEmulatorFunctions.template.yul | 3 ++- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index c0fdc0010..7cb857ed1 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,15 +122,15 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000c17a11dbdb15973a96a4ddd5b95f19843ea7e7affa8f63fe0e5e4ef5b7c", - "sourceCodeHash": "0x5b6098d09a93c5a55cc119d6a30a6e8e446db778af4a4350deb1b5d8ba5c764a" + "bytecodeHash": "0x01000c17f157cd87a1e8d9d8c0e9fb8a1b3ecd0409e68769365f5014e4b053ff", + "sourceCodeHash": "0xd17982c310a48c4edc2c5351b2a4372a0c161719f09c73de8aa8a960a2eae1a5" }, { "contractName": "EvmGasManager", "bytecodePath": "contracts-preprocessed/artifacts/EvmGasManager.yul/EvmGasManager.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmGasManager.yul", - "bytecodeHash": "0x01000059d5a1736d5865f592c5dcf2e301697b83d4abfdc4a8fa2b5cfe88de8d", - "sourceCodeHash": "0xad51904bf2b8cd81cb66962c3211c9514e6ccd0c5bd30288d1f5697b29639fcb" + "bytecodeHash": "0x010000610462e7b494ad4db402ee0ca6369f20d9267aa2b5aa51886d869d16a2", + "sourceCodeHash": "0x5d683d77785f928d62a6b876cec35e4fb057db809e2328ad3df329a5d88a32c3" }, { "contractName": "CodeOracle", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index b14bcaf04..156e3da38 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -597,8 +597,9 @@ object "EvmEmulator" { // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) // non-standard selector 0x04 mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) + mstore(1, caller()) - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 33) let _returndatasize := returndatasize() if _returndatasize { @@ -3590,8 +3591,9 @@ object "EvmEmulator" { // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) // non-standard selector 0x04 mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) + mstore(1, caller()) - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 33) let _returndatasize := returndatasize() if _returndatasize { diff --git a/system-contracts/contracts/EvmGasManager.yul b/system-contracts/contracts/EvmGasManager.yul index 07eac468f..02fb6c148 100644 --- a/system-contracts/contracts/EvmGasManager.yul +++ b/system-contracts/contracts/EvmGasManager.yul @@ -93,6 +93,11 @@ object "EvmGasManager" { } } + function warmAccount(account) { + let transientSlot := or(IS_ACCOUNT_WARM_PREFIX(), account) + tstore(transientSlot, 1) + } + //////////////////////////////////////////////////////////////// // FALLBACK //////////////////////////////////////////////////////////////// @@ -209,9 +214,15 @@ object "EvmGasManager" { } // We do not have active frame. This means that the EVM contract was called from the EraVM contract. - // We should mark the EVM contract as warm. - let isSenderWarmSlot := or(IS_ACCOUNT_WARM_PREFIX(), caller()) - tstore(isSenderWarmSlot, 1) + // mark caller and txorigin as warm + let _msgsender := calldataload(1) + let _origin := origin() + warmAccount(_msgsender) + if iszero(eq(_msgsender, _origin)) { + warmAccount(_origin) + } + // We should mark the EVM contract as warm too. + warmAccount(caller()) return(0x0, 0x0) } default { diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 81c7fe614..5e37891fd 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -535,8 +535,9 @@ function consumeEvmFrame() -> passGas, isStatic, callerEVM { // function consumeEvmFrame() external returns (uint256 passGas, uint256 auxDataRes) // non-standard selector 0x04 mstore(0, 0x0400000000000000000000000000000000000000000000000000000000000000) + mstore(1, caller()) - performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 33) let _returndatasize := returndatasize() if _returndatasize { From 3cb65f6bd0ddc6cf258efd6decde01fb3c37ae78 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 28 Oct 2024 09:13:17 +0100 Subject: [PATCH 124/183] feat(EVM): Simplify returngas from constructor (#1037) --- system-contracts/SystemContractsHashes.json | 36 +++++++++--------- .../contracts/ContractDeployer.sol | 34 ++++++----------- system-contracts/contracts/EvmEmulator.yul | 38 +++++++++++++------ .../interfaces/IContractDeployer.sol | 2 - .../EvmEmulatorFunctions.template.yul | 19 +++++++--- 5 files changed, 68 insertions(+), 61 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 7cb857ed1..6c11c5916 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": "0x0100007717dc02746f2cb709926f52fd61d96cb46101936b1185de956b574682", + "bytecodeHash": "0x0100007757f0a993c2b61e4b7b980eac7c16f9461d56b872befad11edf1791ef", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f13cbea31bcb77c670158b426d21e8f580951a7fc4ef9b2212ab67a30f", + "bytecodeHash": "0x010006f1164848f2e7669df28198a273458ba1fdf1ed0a04321289821d624ad4", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x010000470f54c0e5cc35e659aefce4a345fde4a905a3396e08e6e08e9502c4a2", + "bytecodeHash": "0x0100004772c49529c6ccb5f6b3b1ea23d7498a172b59f3aa8797443ab7ec423a", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013fc97f375809db1ce6fb6e5951a6a2e52361002d148a1768eaf6bad9e7", + "bytecodeHash": "0x0100013f346ef598ecf8a5ba86e2fa4b306816a89a5a96af611047f3508faf03", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x01000699eff3447b6d51bb1eaf32037bd4aafbbb1baa9a70f76125830ee97937", - "sourceCodeHash": "0x9ad8797aa39ae899362ed936542fe13160ef2a2ed95d67c2d66ac62077e61059" + "bytecodeHash": "0x010006975c637c78ca0e91e71c84b324c6e95c733fc041a0390a02656caa03c6", + "sourceCodeHash": "0x763a3e674b2900206bded35a5d390136da61cb043c86f2f4e0633d666313be25" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003f8b2f60eb000b89fd840c27aec320d8df5e2c860b6d3bd0f6010762ec", + "bytecodeHash": "0x0100003fc7635b13ed69e2a8e85908317afa68eee660998372981c7ca9991aaa", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x01000509cce015327bf1a00b6007b69a884240bd559faa2fa2f45bfa9e9abd96", + "bytecodeHash": "0x010005096489d3a6c7c9d18750a4bda0f78c7a7f71ec540cb9b0fb8f2970922b", "sourceCodeHash": "0xef448fac6b6f1c217b6495ee134a3553e02dfb920fd46bc71de33672e64d9ab8" }, { @@ -59,56 +59,56 @@ "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033536138bb4d3541b826f736392db784f4d1f419b8f98edbdf9ec99b05", + "bytecodeHash": "0x010000333575bcc1f34a79d1b43bb8f69813d35463b602e8e1fb88d85806aee1", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cd5b164d338301040c3f5a2c73c775b2e0f7b7c5049dc2198d912e8d95", + "bytecodeHash": "0x010000cdc5734c8109be1afdc5ad40c84157d9f19bc1967d8a128444bcce0360", "sourceCodeHash": "0x851fb5e170dfde39f1f9bc74654ec0b8f8f1d4c2fb20c06c77844c1e3ee0659a" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000265b0203371672d9ba8d5f4ae92635606bf9c77b550c387917bddb9acdf", + "bytecodeHash": "0x01000265966dd95109bdd779e6deeb4f531d0cd983fb053ed77fbb982f94607b", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f36487ed4282e33a1f8a323586e769a33409c55ddccb1d839117bfbe9c", + "bytecodeHash": "0x010000f33e4c891018536ca207056f7536854b030d847fdd7f21eb5576b30ed4", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005946d91043ea599c05aa4d735d401d7aa6600b5b12f967c6ec8c983fb7", + "bytecodeHash": "0x01000059700408fe641af24437be3a197adfa4798b943594dc83f10a70bae855", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cf9366b12f1aed3bf74174fbca6eb1a6ab841830659a527408c11d3a32", + "bytecodeHash": "0x010000cffce37e7325318c746f5af8bd8d5f22236eabe2c5c78fc2acca5b418d", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041d59901297fd33c6a872493d201611711ab0e5a44ba4c24f4671756b2", + "bytecodeHash": "0x01000041a25a3ab6180cb1d752e742d9e39c8637b6c9e1e64a52d002f761b32d", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c5238dcdd879430a91bf5ce05aa4f2d57ef5044b5e460a45bb426267fd", + "bytecodeHash": "0x010001c56a15564c7f07cc0dc68099436b1b40110f2d011b957860e324f948d7", "sourceCodeHash": "0xe2f6eb015d260aafe9405b28ef3ec27921add4de7f329b7ef61e0aa6c9365e29" }, { @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000c17f157cd87a1e8d9d8c0e9fb8a1b3ecd0409e68769365f5014e4b053ff", - "sourceCodeHash": "0xd17982c310a48c4edc2c5351b2a4372a0c161719f09c73de8aa8a960a2eae1a5" + "bytecodeHash": "0x01000c11e73a6952799a1f6104b39b411edda95ec98ea3023b45b019170d1dca", + "sourceCodeHash": "0x8e2f59560e10ece459fbde4ad7355df59a330055a4bbdb8b2d4500e4f35c1efe" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index fbcac4c33..c9d0a1850 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -27,7 +27,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { mapping(address => AccountInfo) internal accountInfo; uint256 private constant EVM_HASHES_PREFIX = 1 << 254; - uint256 private constant CONSTRUCTOR_RETURN_GAS_TSLOT = 1; uint256 private constant ALLOWED_BYTECODE_TYPES_MODE_SLOT = 2; modifier onlySelf() { @@ -46,12 +45,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { mode = _getAllowedBytecodeTypesMode(); } - function constructorReturnGas() external view returns (uint256 returnGas) { - assembly { - returnGas := tload(CONSTRUCTOR_RETURN_GAS_TSLOT) - } - } - /// @notice Returns information about a certain account. function getAccountInfo(address _address) external view returns (AccountInfo memory info) { return accountInfo[_address]; @@ -248,7 +241,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { function createEvmFromEmulator( address newAddress, bytes calldata _initCode - ) external payable onlySystemCallFromEvmEmulator returns (address) { + ) external payable onlySystemCallFromEvmEmulator returns (uint256, address) { uint32 providedErgs; uint32 stipend = EVM_GAS_STIPEND; assembly { @@ -257,8 +250,8 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { providedErgs := sub(_gas, stipend) } } - _evmDeployOnAddress(providedErgs, msg.sender, newAddress, _initCode); - return newAddress; + uint256 constructorReturnEvmGas = _evmDeployOnAddress(providedErgs, msg.sender, newAddress, _initCode); + return (constructorReturnEvmGas, newAddress); } /// @notice Deploys a contract account with similar address derivation rules to the EVM's `CREATE2` opcode. @@ -423,7 +416,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address _sender, address _newAddress, bytes calldata _initCode - ) internal { + ) internal returns (uint256 constructorReturnEvmGas) { if (_getAllowedBytecodeTypesMode() != AllowedBytecodeTypes.EraVmAndEVM) { revert EVMEmulationNotSupported(); } @@ -431,7 +424,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(_gasToPass, _sender, _newAddress, AccountAbstractionVersion.None, _initCode); + return _performDeployOnAddressEVM(_gasToPass, _sender, _newAddress, AccountAbstractionVersion.None, _initCode); } /// @notice Deploy a certain bytecode on the address. @@ -476,7 +469,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address _newAddress, AccountAbstractionVersion _aaVersion, bytes calldata _input - ) internal { + ) internal returns (uint256 constructorReturnEvmGas) { AccountInfo memory newAccountInfo; newAccountInfo.supportedAAVersion = _aaVersion; // Accounts have sequential nonces by default. @@ -486,8 +479,8 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { // 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(_gasToPass, _sender, _newAddress, _input); + // We will store dummy constructing bytecode hash to trigger EVM emulator in constructor call + return _constructEVMContract(_gasToPass, _sender, _newAddress, _input); } /// @notice Check that bytecode hash is marked as known on the `KnownCodeStorage` system contracts @@ -564,7 +557,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address _sender, address _newAddress, bytes calldata _input - ) internal { + ) internal returns (uint256 constructorReturnEvmGas) { uint256 value = msg.value; // 1. Transfer the balance to the new address on the constructor call. if (value > 0) { @@ -594,10 +587,9 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _isSystem: false }); - uint256 constructorReturnGas; assembly { let dataLen := mload(paddedBytecode) - constructorReturnGas := mload(add(paddedBytecode, dataLen)) + constructorReturnEvmGas := mload(add(paddedBytecode, dataLen)) mstore(paddedBytecode, sub(dataLen, 0x20)) } @@ -612,11 +604,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _setEvmCodeHash(_newAddress, evmBytecodeHash); - assembly { - tstore(CONSTRUCTOR_RETURN_GAS_TSLOT, constructorReturnGas) - } - - emit ContractDeployed(_sender, evmBytecodeHash, _newAddress); + emit ContractDeployed(_sender, versionedCodeHash, _newAddress); } function _setEvmCodeHash(address _address, bytes32 _hash) internal { diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 156e3da38..f65c552e8 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1109,9 +1109,7 @@ object "EvmEmulator" { gasLeft := _saveReturndataAfterEVMCall(0, 0) } default { - returndatacopy(0, 0, 32) - addr := mload(0) - gasLeft := _fetchConstructorReturnGas() + gasLeft, addr := _saveConstructorReturnGas() } let gasUsed := sub(gasForTheCall, gasLeft) @@ -1138,9 +1136,18 @@ object "EvmEmulator" { } } - function _fetchConstructorReturnGas() -> gasLeft { - mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - gasLeft := fetchFromSystemContract(DEPLOYER_SYSTEM_CONTRACT(), 4) + function _saveConstructorReturnGas() -> gasLeft, addr { + loadReturndataIntoActivePtr() + + if gt(returndatasize(), 63) { // >= 64 + // ContractDeployer returns (uint256 gasLeft, address createdContract) + returndatacopy(0, 0, 64) + gasLeft := mload(0) + addr := mload(32) + } + // else: unexpected return data after constructor succeeded, should never happen. + + _eraseReturndataPointer() } //////////////////////////////////////////////////////////////// @@ -4103,9 +4110,7 @@ object "EvmEmulator" { gasLeft := _saveReturndataAfterEVMCall(0, 0) } default { - returndatacopy(0, 0, 32) - addr := mload(0) - gasLeft := _fetchConstructorReturnGas() + gasLeft, addr := _saveConstructorReturnGas() } let gasUsed := sub(gasForTheCall, gasLeft) @@ -4132,9 +4137,18 @@ object "EvmEmulator" { } } - function _fetchConstructorReturnGas() -> gasLeft { - mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - gasLeft := fetchFromSystemContract(DEPLOYER_SYSTEM_CONTRACT(), 4) + function _saveConstructorReturnGas() -> gasLeft, addr { + loadReturndataIntoActivePtr() + + if gt(returndatasize(), 63) { // >= 64 + // ContractDeployer returns (uint256 gasLeft, address createdContract) + returndatacopy(0, 0, 64) + gasLeft := mload(0) + addr := mload(32) + } + // else: unexpected return data after constructor succeeded, should never happen. + + _eraseReturndataPointer() } //////////////////////////////////////////////////////////////// diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index ef8c83f95..ef94427a8 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -108,8 +108,6 @@ interface IContractDeployer { function evmCodeHash(address) external view returns (bytes32); - function constructorReturnGas() external view returns (uint256); - /// @notice Changes what types of bytecodes are allowed to be deployed on the chain. Can be used only during upgrades. /// @param newAllowedBytecodeTypes The new allowed bytecode types mode. function setAllowedBytecodeTypesToDeploy(uint256 newAllowedBytecodeTypes) external; diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 5e37891fd..0e3c0833a 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -1047,9 +1047,7 @@ function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> gasLeft := _saveReturndataAfterEVMCall(0, 0) } default { - returndatacopy(0, 0, 32) - addr := mload(0) - gasLeft := _fetchConstructorReturnGas() + gasLeft, addr := _saveConstructorReturnGas() } let gasUsed := sub(gasForTheCall, gasLeft) @@ -1076,9 +1074,18 @@ function performSystemCallForCreate(value, bytecodeStart, bytecodeLen) -> succes } } -function _fetchConstructorReturnGas() -> gasLeft { - mstore(0, 0x24E5AB4A00000000000000000000000000000000000000000000000000000000) - gasLeft := fetchFromSystemContract(DEPLOYER_SYSTEM_CONTRACT(), 4) +function _saveConstructorReturnGas() -> gasLeft, addr { + loadReturndataIntoActivePtr() + + if gt(returndatasize(), 63) { // >= 64 + // ContractDeployer returns (uint256 gasLeft, address createdContract) + returndatacopy(0, 0, 64) + gasLeft := mload(0) + addr := mload(32) + } + // else: unexpected return data after constructor succeeded, should never happen. + + _eraseReturndataPointer() } //////////////////////////////////////////////////////////////// From 82aa1a2da4977f72c9f9998dbba53149cb74e804 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 28 Oct 2024 10:33:23 +0100 Subject: [PATCH 125/183] fix(EVM): Fix TODOs in EvmGasManager (#1038) --- system-contracts/contracts/EvmGasManager.yul | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/system-contracts/contracts/EvmGasManager.yul b/system-contracts/contracts/EvmGasManager.yul index 02fb6c148..151680825 100644 --- a/system-contracts/contracts/EvmGasManager.yul +++ b/system-contracts/contracts/EvmGasManager.yul @@ -23,7 +23,7 @@ object "EvmGasManager" { } function PRECOMPILES_END() -> value { - value := sub(0xffff, 1) // TODO should we exclude system contracts? + value := 0x0a // As in Cancun } function EVM_GAS_SLOT() -> value { @@ -71,7 +71,9 @@ object "EvmGasManager" { let notSystemCall := iszero(and(callFlags, 2)) if notSystemCall { - revert(0, 0) // TODO errors? + // error CallerMustBeEvmContract() + mstore(0, 0xBE4BF9E400000000000000000000000000000000000000000000000000000000) + revert(0, 32) } // SELFDESTRUCT is not supported, so it is ok to cache here @@ -82,7 +84,9 @@ object "EvmGasManager" { isEVM := eq(shr(248, versionedCodeHash), 2) if iszero(isEVM) { - revert(0, 0) + // error CallerMustBeEvmContract() + mstore(0, 0xBE4BF9E400000000000000000000000000000000000000000000000000000000) + revert(0, 32) } // we will not cache contract if it is being constructed @@ -118,7 +122,8 @@ object "EvmGasManager" { let wasWarm := true - if gt(account, PRECOMPILES_END()) { + // precompiles are always warm + if or(iszero(account), gt(account, PRECOMPILES_END())) { let transientSlot := or(IS_ACCOUNT_WARM_PREFIX(), account) wasWarm := tload(transientSlot) @@ -223,6 +228,7 @@ object "EvmGasManager" { } // We should mark the EVM contract as warm too. warmAccount(caller()) + warmAccount(coinbase()) // and the coinbase too return(0x0, 0x0) } default { From 96e989f1405974e7b5bac9916ba9b08af59a1b50 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 28 Oct 2024 10:33:58 +0100 Subject: [PATCH 126/183] fix(EVM): Fix zknative calls (#1034) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 438 +++++++++--------- .../EvmEmulatorFunctions.template.yul | 217 +++++---- .../evm-emulator/EvmEmulatorLoop.template.yul | 2 +- 4 files changed, 323 insertions(+), 338 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 6c11c5916..ca8c50ebd 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000c11e73a6952799a1f6104b39b411edda95ec98ea3023b45b019170d1dca", - "sourceCodeHash": "0x8e2f59560e10ece459fbde4ad7355df59a330055a4bbdb8b2d4500e4f35c1efe" + "bytecodeHash": "0x01000cb5e90253e30cb34af94cc4194651115f7c693cb98911a96fe832490573", + "sourceCodeHash": "0xd72da6a50f2fbe50fac063397b0aa18c77ea7865dc3059705e062612955fca91" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index f65c552e8..a35dc9c3a 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -167,7 +167,7 @@ object "EvmEmulator" { max := 0x400000 // 4MB } - function MAX_MEMORY_FRAME() -> max { + function MAX_MEMORY_SLOT() -> max { max := add(MEM_OFFSET(), MAX_POSSIBLE_MEM_LEN()) } @@ -175,10 +175,6 @@ object "EvmEmulator" { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } - function INF_PASS_GAS() -> inf { - inf := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - } - // Each evm gas is 5 zkEVM one function GAS_DIVISOR() -> gas_div { gas_div := 5 } @@ -277,10 +273,20 @@ object "EvmEmulator" { } } + function expandMemory2(retOffset, retSize, argsOffset, argsSize) -> maxExpand { + switch lt(add(retOffset, retSize), add(argsOffset, argsSize)) + case 0 { + maxExpand := expandMemory(retOffset, retSize) + } + default { + maxExpand := expandMemory(argsOffset, argsSize) + } + } + function checkMemIsAccessible(index, offset) { checkOverflow(index, offset) - if gt(add(index, offset), MAX_MEMORY_FRAME()) { + if gt(add(index, offset), MAX_MEMORY_SLOT()) { panic() } } @@ -645,7 +651,7 @@ object "EvmEmulator" { } // memory_expansion_cost - gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) if gt(value, 0) { gasUsed := add(gasUsed, 9000) // positive_value_cost @@ -663,33 +669,17 @@ object "EvmEmulator" { gasToPass := add(gasToPass, 2300) } - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - if precompileCost { - if lt(gasToPass, precompileCost) { - gasToPass := 0 - } - } - - let success, frameGasLeft := _performCall( + let success, frameGasLeft := _genericCall( addr, gasToPass, value, add(argsOffset, MEM_OFFSET()), argsSize, add(retOffset, MEM_OFFSET()), - retSize + retSize, + false ) - if precompileCost { - switch success - case 0 { - frameGasLeft := 0 // consume all provided gas - } - default { - frameGasLeft := sub(gasToPass, precompileCost) - } - } - newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } @@ -709,43 +699,29 @@ object "EvmEmulator" { checkMemIsAccessible(argsOffset, argsSize) checkMemIsAccessible(retOffset, retSize) - let gasUsed := 100 + let gasUsed := 100 // warm address access cost if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 + gasUsed := 2600 // cold address access cost } - gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + // memory_expansion_cost + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) gasToPass := capGasForCall(evmGasLeft, gasToPass) evmGasLeft := sub(evmGasLeft, gasToPass) - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - if precompileCost { - if lt(gasToPass, precompileCost) { - gasToPass := 0 - } - } - - let success, frameGasLeft := _performStaticCall( + let success, frameGasLeft := _genericCall( addr, gasToPass, + 0, add(MEM_OFFSET(), argsOffset), argsSize, add(MEM_OFFSET(), retOffset), - retSize + retSize, + true ) - if precompileCost { - switch success - case 0 { - frameGasLeft := 0 // consume all provided gas - } - default { - frameGasLeft := sub(gasToPass, precompileCost) - } - } - newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } @@ -766,16 +742,17 @@ object "EvmEmulator" { checkMemIsAccessible(argsOffset, argsSize) checkMemIsAccessible(retOffset, retSize) - let gasUsed := 100 + let gasUsed := 100 // warm address access cost if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 + gasUsed := 2600 // cold address access cost } - gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + // memory_expansion_cost + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) - // it is not possible to delegatecall precompiles + // it is also not possible to delegatecall precompiles if iszero(isEvmContract(addr)) { revertWithGas(evmGasLeft) } @@ -799,78 +776,106 @@ object "EvmEmulator" { stackHead := success } - function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { switch isEvmContract(addr) case 0 { - // zkEVM native - let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas - let zkEvmGasBefore := gas() - success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) - - if gt(gasToPass, gasUsed) { - frameGasLeft := sub(gasToPass, gasUsed) // TODO check + // zkEVM native call + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch precompileCost + case 0 { + // just smart contract + success, frameGasLeft := callZkVmNative(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) + } + default { + // precompile + success, frameGasLeft := callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) } } default { - pushEvmFrame(gasToPass, false) - // VM will add EVM_GAS_STIPEND() to gas for this call - // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract - // so we need to add some gas for MsgValueSimulator - success := call(add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), providedErgs()), addr, value, argsOffset, argsSize, 0, 0) + pushEvmFrame(gasToPass, isStatic) + // VM will add EVM_GAS_STIPEND() to gas for this call, but if value != 0 we will firstly call MsgValueSimulator contract + // which is zkVM system contract. So we need to add some gas for MsgValueSimulator + let ergsToPass := providedErgs() + if value { + ergsToPass := add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), ergsToPass) + } + success := call(ergsToPass, addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } - function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch isEvmContract(addr) - case 0 { - // zkEVM native - let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas - let zkEvmGasBefore := gas() - success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) + function callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { + let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts + if lt(gasToPass, precompileCost) { + zkVmGasToPass := 0 // in EVM precompile should revert consuming all gas in that case + } - if gt(gasToPass, gasUsed) { - frameGasLeft := sub(gasToPass, gasUsed) // TODO check - } + switch isStatic + case 0 { + success := call(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) } default { - pushEvmFrame(gasToPass, true) - success := staticcall(providedErgs(), addr, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + success := staticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) } - } + + _saveReturndataAfterZkEVMCall() - function calcUsedEvmGasByZkVmCall(zkEvmGasBefore) -> evmGasUsed { - let zkevmGasUsed := sub(zkEvmGasBefore, gas()) // caller should guarantee correctness - // should not overflow, VM can't pass more than u32 of gas - evmGasUsed := div(add(zkevmGasUsed, sub(GAS_DIVISOR(), 1)), GAS_DIVISOR()) // rounding up + if success { + frameGasLeft := sub(gasToPass, precompileCost) + } + // else consume all provided gas } - function calcZkVmGasForCall(evmGasToPass, addr) -> zkevmGas { - zkevmGas := mul(evmGasToPass, GAS_DIVISOR()) + // Call native ZkVm contract from EVM context + function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { + let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas + let decommitZkVmGasCost := decommitmentCost(addr) - // charge for contract decommitment - let byteSize := extcodesize(addr) - let decommitGasCost := mul( - div(add(byteSize, 31), 32), // rounding up - DECOMMIT_COST_PER_WORD() - ) + // we are going to charge decommit cost even if address is already warm + // decommit cost is subtracted from the callee frame + switch gt(decommitZkVmGasCost, zkEvmGasToPass) + case 0 { + zkEvmGasToPass := sub(zkEvmGasToPass, decommitZkVmGasCost) + } + default { + zkEvmGasToPass := 0 + } + + if gt(zkEvmGasToPass, UINT32_MAX()) { // just in case + zkEvmGasToPass := UINT32_MAX() + } - if gt(decommitGasCost, zkevmGas) { - zkevmGas := 0 + let zkEvmGasBefore := gas() + switch isStatic + case 0 { + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + } + default { + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) } + let zkEvmGasUsed := sub(zkEvmGasBefore, gas()) - zkevmGas := sub(zkevmGas, decommitGasCost) + _saveReturndataAfterZkEVMCall() + + if gt(zkEvmGasUsed, zkEvmGasBefore) { // overflow case + zkEvmGasUsed := zkEvmGasToPass // should never happen + } - if gt(zkevmGas, UINT32_MAX()) { // Should never happen - zkevmGas := UINT32_MAX() + // refund gas + if gt(zkEvmGasToPass, zkEvmGasUsed) { + frameGasLeft := div(sub(zkEvmGasToPass, zkEvmGasUsed), GAS_DIVISOR()) } } + function decommitmentCost(addr) -> cost { + // charge for contract decommitment + let byteSize := extcodesize(addr) + cost := mul( + div(add(byteSize, 31), 32), // rounding up + DECOMMIT_COST_PER_WORD() + ) + } + function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 gasToPass := oldGasToPass @@ -879,16 +884,6 @@ object "EvmEmulator" { } } - function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> maxExpand { - switch lt(add(retOffset, retSize), add(argsOffset, argsSize)) - case 0 { - maxExpand := expandMemory(retOffset, retSize) - } - default { - maxExpand := expandMemory(argsOffset, argsSize) - } - } - // 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. @@ -1049,7 +1044,7 @@ object "EvmEmulator" { } function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { - let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) + let gasForTheCall := capGasForCall(evmGasLeftOld, evmGasLeftOld) // pass 63/64 of remaining gas let bytecodeHash := 0 if isCreate2 { @@ -2024,7 +2019,7 @@ object "EvmEmulator" { checkMemIsAccessible(destOffset, size) // dynamic_gas = 3 * words_copied + memory_expansion_cost - let dynamicGas := getMaxMemoryExpansionCost(offset, size, destOffset, size) + let dynamicGas := expandMemory2(offset, size, destOffset, size) let wordsCopied := div(add(size, 31), 32) // div rounding up dynamicGas := add(dynamicGas, mul(3, wordsCopied)) @@ -3168,7 +3163,7 @@ object "EvmEmulator" { max := 0x400000 // 4MB } - function MAX_MEMORY_FRAME() -> max { + function MAX_MEMORY_SLOT() -> max { max := add(MEM_OFFSET(), MAX_POSSIBLE_MEM_LEN()) } @@ -3176,10 +3171,6 @@ object "EvmEmulator" { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } - function INF_PASS_GAS() -> inf { - inf := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - } - // Each evm gas is 5 zkEVM one function GAS_DIVISOR() -> gas_div { gas_div := 5 } @@ -3278,10 +3269,20 @@ object "EvmEmulator" { } } + function expandMemory2(retOffset, retSize, argsOffset, argsSize) -> maxExpand { + switch lt(add(retOffset, retSize), add(argsOffset, argsSize)) + case 0 { + maxExpand := expandMemory(retOffset, retSize) + } + default { + maxExpand := expandMemory(argsOffset, argsSize) + } + } + function checkMemIsAccessible(index, offset) { checkOverflow(index, offset) - if gt(add(index, offset), MAX_MEMORY_FRAME()) { + if gt(add(index, offset), MAX_MEMORY_SLOT()) { panic() } } @@ -3646,7 +3647,7 @@ object "EvmEmulator" { } // memory_expansion_cost - gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) if gt(value, 0) { gasUsed := add(gasUsed, 9000) // positive_value_cost @@ -3664,33 +3665,17 @@ object "EvmEmulator" { gasToPass := add(gasToPass, 2300) } - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - if precompileCost { - if lt(gasToPass, precompileCost) { - gasToPass := 0 - } - } - - let success, frameGasLeft := _performCall( + let success, frameGasLeft := _genericCall( addr, gasToPass, value, add(argsOffset, MEM_OFFSET()), argsSize, add(retOffset, MEM_OFFSET()), - retSize + retSize, + false ) - if precompileCost { - switch success - case 0 { - frameGasLeft := 0 // consume all provided gas - } - default { - frameGasLeft := sub(gasToPass, precompileCost) - } - } - newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } @@ -3710,43 +3695,29 @@ object "EvmEmulator" { checkMemIsAccessible(argsOffset, argsSize) checkMemIsAccessible(retOffset, retSize) - let gasUsed := 100 + let gasUsed := 100 // warm address access cost if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 + gasUsed := 2600 // cold address access cost } - gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + // memory_expansion_cost + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) gasToPass := capGasForCall(evmGasLeft, gasToPass) evmGasLeft := sub(evmGasLeft, gasToPass) - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - if precompileCost { - if lt(gasToPass, precompileCost) { - gasToPass := 0 - } - } - - let success, frameGasLeft := _performStaticCall( + let success, frameGasLeft := _genericCall( addr, gasToPass, + 0, add(MEM_OFFSET(), argsOffset), argsSize, add(MEM_OFFSET(), retOffset), - retSize + retSize, + true ) - if precompileCost { - switch success - case 0 { - frameGasLeft := 0 // consume all provided gas - } - default { - frameGasLeft := sub(gasToPass, precompileCost) - } - } - newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } @@ -3767,16 +3738,17 @@ object "EvmEmulator" { checkMemIsAccessible(argsOffset, argsSize) checkMemIsAccessible(retOffset, retSize) - let gasUsed := 100 + let gasUsed := 100 // warm address access cost if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 + gasUsed := 2600 // cold address access cost } - gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + // memory_expansion_cost + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) - // it is not possible to delegatecall precompiles + // it is also not possible to delegatecall precompiles if iszero(isEvmContract(addr)) { revertWithGas(evmGasLeft) } @@ -3800,78 +3772,106 @@ object "EvmEmulator" { stackHead := success } - function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { + function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { switch isEvmContract(addr) case 0 { - // zkEVM native - let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas - let zkEvmGasBefore := gas() - success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) - - if gt(gasToPass, gasUsed) { - frameGasLeft := sub(gasToPass, gasUsed) // TODO check + // zkEVM native call + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch precompileCost + case 0 { + // just smart contract + success, frameGasLeft := callZkVmNative(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) + } + default { + // precompile + success, frameGasLeft := callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) } } default { - pushEvmFrame(gasToPass, false) - // VM will add EVM_GAS_STIPEND() to gas for this call - // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract - // so we need to add some gas for MsgValueSimulator - success := call(add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), providedErgs()), addr, value, argsOffset, argsSize, 0, 0) + pushEvmFrame(gasToPass, isStatic) + // VM will add EVM_GAS_STIPEND() to gas for this call, but if value != 0 we will firstly call MsgValueSimulator contract + // which is zkVM system contract. So we need to add some gas for MsgValueSimulator + let ergsToPass := providedErgs() + if value { + ergsToPass := add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), ergsToPass) + } + success := call(ergsToPass, addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } - function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch isEvmContract(addr) - case 0 { - // zkEVM native - let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas - let zkEvmGasBefore := gas() - success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) + function callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { + let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts + if lt(gasToPass, precompileCost) { + zkVmGasToPass := 0 // in EVM precompile should revert consuming all gas in that case + } - if gt(gasToPass, gasUsed) { - frameGasLeft := sub(gasToPass, gasUsed) // TODO check - } + switch isStatic + case 0 { + success := call(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) } default { - pushEvmFrame(gasToPass, true) - success := staticcall(providedErgs(), addr, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + success := staticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) } - } + + _saveReturndataAfterZkEVMCall() - function calcUsedEvmGasByZkVmCall(zkEvmGasBefore) -> evmGasUsed { - let zkevmGasUsed := sub(zkEvmGasBefore, gas()) // caller should guarantee correctness - // should not overflow, VM can't pass more than u32 of gas - evmGasUsed := div(add(zkevmGasUsed, sub(GAS_DIVISOR(), 1)), GAS_DIVISOR()) // rounding up + if success { + frameGasLeft := sub(gasToPass, precompileCost) + } + // else consume all provided gas } - function calcZkVmGasForCall(evmGasToPass, addr) -> zkevmGas { - zkevmGas := mul(evmGasToPass, GAS_DIVISOR()) + // Call native ZkVm contract from EVM context + function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { + let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas + let decommitZkVmGasCost := decommitmentCost(addr) - // charge for contract decommitment - let byteSize := extcodesize(addr) - let decommitGasCost := mul( - div(add(byteSize, 31), 32), // rounding up - DECOMMIT_COST_PER_WORD() - ) + // we are going to charge decommit cost even if address is already warm + // decommit cost is subtracted from the callee frame + switch gt(decommitZkVmGasCost, zkEvmGasToPass) + case 0 { + zkEvmGasToPass := sub(zkEvmGasToPass, decommitZkVmGasCost) + } + default { + zkEvmGasToPass := 0 + } - if gt(decommitGasCost, zkevmGas) { - zkevmGas := 0 + if gt(zkEvmGasToPass, UINT32_MAX()) { // just in case + zkEvmGasToPass := UINT32_MAX() + } + + let zkEvmGasBefore := gas() + switch isStatic + case 0 { + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + } + default { + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) } + let zkEvmGasUsed := sub(zkEvmGasBefore, gas()) - zkevmGas := sub(zkevmGas, decommitGasCost) + _saveReturndataAfterZkEVMCall() + + if gt(zkEvmGasUsed, zkEvmGasBefore) { // overflow case + zkEvmGasUsed := zkEvmGasToPass // should never happen + } - if gt(zkevmGas, UINT32_MAX()) { // Should never happen - zkevmGas := UINT32_MAX() + // refund gas + if gt(zkEvmGasToPass, zkEvmGasUsed) { + frameGasLeft := div(sub(zkEvmGasToPass, zkEvmGasUsed), GAS_DIVISOR()) } } + function decommitmentCost(addr) -> cost { + // charge for contract decommitment + let byteSize := extcodesize(addr) + cost := mul( + div(add(byteSize, 31), 32), // rounding up + DECOMMIT_COST_PER_WORD() + ) + } + function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 gasToPass := oldGasToPass @@ -3880,16 +3880,6 @@ object "EvmEmulator" { } } - function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> maxExpand { - switch lt(add(retOffset, retSize), add(argsOffset, argsSize)) - case 0 { - maxExpand := expandMemory(retOffset, retSize) - } - default { - maxExpand := expandMemory(argsOffset, argsSize) - } - } - // 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. @@ -4050,7 +4040,7 @@ object "EvmEmulator" { } function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { - let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) + let gasForTheCall := capGasForCall(evmGasLeftOld, evmGasLeftOld) // pass 63/64 of remaining gas let bytecodeHash := 0 if isCreate2 { @@ -5025,7 +5015,7 @@ object "EvmEmulator" { checkMemIsAccessible(destOffset, size) // dynamic_gas = 3 * words_copied + memory_expansion_cost - let dynamicGas := getMaxMemoryExpansionCost(offset, size, destOffset, size) + let dynamicGas := expandMemory2(offset, size, destOffset, size) let wordsCopied := div(add(size, 31), 32) // div rounding up dynamicGas := add(dynamicGas, mul(3, wordsCopied)) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 0e3c0833a..7af2ecc82 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -105,7 +105,7 @@ function MAX_POSSIBLE_MEM_LEN() -> max { max := 0x400000 // 4MB } -function MAX_MEMORY_FRAME() -> max { +function MAX_MEMORY_SLOT() -> max { max := add(MEM_OFFSET(), MAX_POSSIBLE_MEM_LEN()) } @@ -113,10 +113,6 @@ function MAX_UINT() -> max_uint { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } -function INF_PASS_GAS() -> inf { - inf := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -} - // Each evm gas is 5 zkEVM one function GAS_DIVISOR() -> gas_div { gas_div := 5 } @@ -215,10 +211,20 @@ function expandMemory(offset, size) -> gasCost { } } +function expandMemory2(retOffset, retSize, argsOffset, argsSize) -> maxExpand { + switch lt(add(retOffset, retSize), add(argsOffset, argsSize)) + case 0 { + maxExpand := expandMemory(retOffset, retSize) + } + default { + maxExpand := expandMemory(argsOffset, argsSize) + } +} + function checkMemIsAccessible(index, offset) { checkOverflow(index, offset) - if gt(add(index, offset), MAX_MEMORY_FRAME()) { + if gt(add(index, offset), MAX_MEMORY_SLOT()) { panic() } } @@ -583,7 +589,7 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe } // memory_expansion_cost - gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) if gt(value, 0) { gasUsed := add(gasUsed, 9000) // positive_value_cost @@ -601,33 +607,17 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe gasToPass := add(gasToPass, 2300) } - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - if precompileCost { - if lt(gasToPass, precompileCost) { - gasToPass := 0 - } - } - - let success, frameGasLeft := _performCall( + let success, frameGasLeft := _genericCall( addr, gasToPass, value, add(argsOffset, MEM_OFFSET()), argsSize, add(retOffset, MEM_OFFSET()), - retSize + retSize, + false ) - if precompileCost { - switch success - case 0 { - frameGasLeft := 0 // consume all provided gas - } - default { - frameGasLeft := sub(gasToPass, precompileCost) - } - } - newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } @@ -647,43 +637,29 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s checkMemIsAccessible(argsOffset, argsSize) checkMemIsAccessible(retOffset, retSize) - let gasUsed := 100 + let gasUsed := 100 // warm address access cost if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 + gasUsed := 2600 // cold address access cost } - gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + // memory_expansion_cost + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) gasToPass := capGasForCall(evmGasLeft, gasToPass) evmGasLeft := sub(evmGasLeft, gasToPass) - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) - if precompileCost { - if lt(gasToPass, precompileCost) { - gasToPass := 0 - } - } - - let success, frameGasLeft := _performStaticCall( + let success, frameGasLeft := _genericCall( addr, gasToPass, + 0, add(MEM_OFFSET(), argsOffset), argsSize, add(MEM_OFFSET(), retOffset), - retSize + retSize, + true ) - if precompileCost { - switch success - case 0 { - frameGasLeft := 0 // consume all provided gas - } - default { - frameGasLeft := sub(gasToPass, precompileCost) - } - } - newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success } @@ -704,16 +680,17 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGa checkMemIsAccessible(argsOffset, argsSize) checkMemIsAccessible(retOffset, retSize) - let gasUsed := 100 + let gasUsed := 100 // warm address access cost if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 + gasUsed := 2600 // cold address access cost } - gasUsed := add(gasUsed, getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize)) + // memory_expansion_cost + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) evmGasLeft := chargeGas(evmGasLeft, gasUsed) - // it is not possible to delegatecall precompiles + // it is also not possible to delegatecall precompiles if iszero(isEvmContract(addr)) { revertWithGas(evmGasLeft) } @@ -737,78 +714,106 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGa stackHead := success } -function _performCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { +function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { switch isEvmContract(addr) case 0 { - // zkEVM native - let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas - let zkEvmGasBefore := gas() - success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) - - if gt(gasToPass, gasUsed) { - frameGasLeft := sub(gasToPass, gasUsed) // TODO check + // zkEVM native call + let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + switch precompileCost + case 0 { + // just smart contract + success, frameGasLeft := callZkVmNative(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) + } + default { + // precompile + success, frameGasLeft := callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) } } default { - pushEvmFrame(gasToPass, false) - // VM will add EVM_GAS_STIPEND() to gas for this call - // but if value != 0 we will firstly call MsgValueSimulator contract, which is zkVM system contract - // so we need to add some gas for MsgValueSimulator - success := call(add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), providedErgs()), addr, value, argsOffset, argsSize, 0, 0) + pushEvmFrame(gasToPass, isStatic) + // VM will add EVM_GAS_STIPEND() to gas for this call, but if value != 0 we will firstly call MsgValueSimulator contract + // which is zkVM system contract. So we need to add some gas for MsgValueSimulator + let ergsToPass := providedErgs() + if value { + ergsToPass := add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), ergsToPass) + } + success := call(ergsToPass, addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) } } -function _performStaticCall(addr, gasToPass, argsOffset, argsSize, retOffset, retSize) -> success, frameGasLeft { - switch isEvmContract(addr) - case 0 { - // zkEVM native - let zkEvmGasToPass := calcZkVmGasForCall(gasToPass, addr) // EVM gas -> ZkVM gas - let zkEvmGasBefore := gas() - success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() - let gasUsed := calcUsedEvmGasByZkVmCall(zkEvmGasBefore) +function callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { + let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts + if lt(gasToPass, precompileCost) { + zkVmGasToPass := 0 // in EVM precompile should revert consuming all gas in that case + } - if gt(gasToPass, gasUsed) { - frameGasLeft := sub(gasToPass, gasUsed) // TODO check - } + switch isStatic + case 0 { + success := call(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) } default { - pushEvmFrame(gasToPass, true) - success := staticcall(providedErgs(), addr, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + success := staticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) } -} + + _saveReturndataAfterZkEVMCall() -function calcUsedEvmGasByZkVmCall(zkEvmGasBefore) -> evmGasUsed { - let zkevmGasUsed := sub(zkEvmGasBefore, gas()) // caller should guarantee correctness - // should not overflow, VM can't pass more than u32 of gas - evmGasUsed := div(add(zkevmGasUsed, sub(GAS_DIVISOR(), 1)), GAS_DIVISOR()) // rounding up + if success { + frameGasLeft := sub(gasToPass, precompileCost) + } + // else consume all provided gas } -function calcZkVmGasForCall(evmGasToPass, addr) -> zkevmGas { - zkevmGas := mul(evmGasToPass, GAS_DIVISOR()) +// Call native ZkVm contract from EVM context +function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { + let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas + let decommitZkVmGasCost := decommitmentCost(addr) - // charge for contract decommitment - let byteSize := extcodesize(addr) - let decommitGasCost := mul( - div(add(byteSize, 31), 32), // rounding up - DECOMMIT_COST_PER_WORD() - ) + // we are going to charge decommit cost even if address is already warm + // decommit cost is subtracted from the callee frame + switch gt(decommitZkVmGasCost, zkEvmGasToPass) + case 0 { + zkEvmGasToPass := sub(zkEvmGasToPass, decommitZkVmGasCost) + } + default { + zkEvmGasToPass := 0 + } - if gt(decommitGasCost, zkevmGas) { - zkevmGas := 0 + if gt(zkEvmGasToPass, UINT32_MAX()) { // just in case + zkEvmGasToPass := UINT32_MAX() + } + + let zkEvmGasBefore := gas() + switch isStatic + case 0 { + success := call(zkEvmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + } + default { + success := staticcall(zkEvmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) } + let zkEvmGasUsed := sub(zkEvmGasBefore, gas()) - zkevmGas := sub(zkevmGas, decommitGasCost) + _saveReturndataAfterZkEVMCall() + + if gt(zkEvmGasUsed, zkEvmGasBefore) { // overflow case + zkEvmGasUsed := zkEvmGasToPass // should never happen + } - if gt(zkevmGas, UINT32_MAX()) { // Should never happen - zkevmGas := UINT32_MAX() + // refund gas + if gt(zkEvmGasToPass, zkEvmGasUsed) { + frameGasLeft := div(sub(zkEvmGasToPass, zkEvmGasUsed), GAS_DIVISOR()) } } +function decommitmentCost(addr) -> cost { + // charge for contract decommitment + let byteSize := extcodesize(addr) + cost := mul( + div(add(byteSize, 31), 32), // rounding up + DECOMMIT_COST_PER_WORD() + ) +} + function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 gasToPass := oldGasToPass @@ -817,16 +822,6 @@ function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { } } -function getMaxMemoryExpansionCost(retOffset, retSize, argsOffset, argsSize) -> maxExpand { - switch lt(add(retOffset, retSize), add(argsOffset, argsSize)) - case 0 { - maxExpand := expandMemory(retOffset, retSize) - } - default { - maxExpand := expandMemory(argsOffset, argsSize) - } -} - // 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. @@ -987,7 +982,7 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, } function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { - let gasForTheCall := capGasForCall(evmGasLeftOld, INF_PASS_GAS()) + let gasForTheCall := capGasForCall(evmGasLeftOld, evmGasLeftOld) // pass 63/64 of remaining gas let bytecodeHash := 0 if isCreate2 { diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 89fbd1504..920ead471 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -820,7 +820,7 @@ for { } true { } { checkMemIsAccessible(destOffset, size) // dynamic_gas = 3 * words_copied + memory_expansion_cost - let dynamicGas := getMaxMemoryExpansionCost(offset, size, destOffset, size) + let dynamicGas := expandMemory2(offset, size, destOffset, size) let wordsCopied := div(add(size, 31), 32) // div rounding up dynamicGas := add(dynamicGas, mul(3, wordsCopied)) From 6f1c55d2accb2e3538f620d941630e214bbe5693 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 28 Oct 2024 10:39:54 +0100 Subject: [PATCH 127/183] chore(EVM): Cleanup in contract deployer (#1039) --- system-contracts/contracts/ContractDeployer.sol | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index c9d0a1850..a8ea69945 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -177,11 +177,14 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.getMinNonce(msg.sender) - 1; } else { // Deploy from EraVM context - senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.getDeploymentNonce(msg.sender); - // TODO only for semantic tests? - if (senderNonce == 0) { - NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); - } + + // #### Uncomment for Solidity semantic tests (EraVM contracts are deployed with 0 nonce, but tests expect 1) + /* + senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.getDeploymentNonce(msg.sender); + if (senderNonce == 0) { + NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); + } + */ senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); } From 520a8588f77d4c7c35800ab5bff70b5195a26d00 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 28 Oct 2024 10:53:51 +0100 Subject: [PATCH 128/183] chore(EVM): Update hashes (#1040) --- system-contracts/SystemContractsHashes.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index ca8c50ebd..0254cefc1 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": "0x010006975c637c78ca0e91e71c84b324c6e95c733fc041a0390a02656caa03c6", - "sourceCodeHash": "0x763a3e674b2900206bded35a5d390136da61cb043c86f2f4e0633d666313be25" + "bytecodeHash": "0x01000671f7ed086cc23329dd16d7e240c19b1a96c6571728c762f705f7c5549b", + "sourceCodeHash": "0x86897736464a0363c5b13c1d5796bfc6ba37e6eaadb848ed13ab69e54b16f21a" }, { "contractName": "Create2Factory", @@ -129,8 +129,8 @@ "contractName": "EvmGasManager", "bytecodePath": "contracts-preprocessed/artifacts/EvmGasManager.yul/EvmGasManager.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmGasManager.yul", - "bytecodeHash": "0x010000610462e7b494ad4db402ee0ca6369f20d9267aa2b5aa51886d869d16a2", - "sourceCodeHash": "0x5d683d77785f928d62a6b876cec35e4fb057db809e2328ad3df329a5d88a32c3" + "bytecodeHash": "0x010000697e213955edae21195912d2900639a2eba6d15f592a12bfb05b350966", + "sourceCodeHash": "0x1eb4cffcd8b9365bed383e199ab169af21a8ba809a685c0a36f89a128d8582f8" }, { "contractName": "CodeOracle", From df1c554661d781d9954add20efe60c8499130303 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 28 Oct 2024 17:50:04 +0100 Subject: [PATCH 129/183] fix(EVM): Fix panics on invalid opcodes (#1041) --- system-contracts/SystemContractsHashes.json | 4 +- system-contracts/contracts/EvmEmulator.yul | 458 +++++++++--------- .../EvmEmulatorFunctions.template.yul | 5 +- .../evm-emulator/EvmEmulatorLoop.template.yul | 2 +- .../EvmEmulatorLoopUnusedOpcodes.template.yul | 222 ++++----- 5 files changed, 347 insertions(+), 344 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 0254cefc1..442620f48 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cb5e90253e30cb34af94cc4194651115f7c693cb98911a96fe832490573", - "sourceCodeHash": "0xd72da6a50f2fbe50fac063397b0aa18c77ea7865dc3059705e062612955fca91" + "bytecodeHash": "0x01000cb54199e828134a56d7302a7ed55ba8f0b54d898aa0f3949ca2774b1643", + "sourceCodeHash": "0xa1ce6b22af5b1be710181ea59b4a76879ccb0d4989d533c92965df1bbaa340b2" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index a35dc9c3a..a4b60bb0f 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -196,8 +196,9 @@ object "EvmEmulator" { // GENERAL FUNCTIONS //////////////////////////////////////////////////////////////// - function $llvm_NoInline_llvm$_revert() { - revert(0, 0) + function $llvm_NoInline_llvm$_panic() { // revert consuming all EVM gas + mstore(0, 0) + revert(0, 32) } function revertWithGas(evmGasLeft) { @@ -2669,340 +2670,340 @@ object "EvmEmulator" { } // We explicitly add unused opcodes to optimize the jump table by compiler. case 0x0C { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x0D { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x0E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x0F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x1E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x1F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x21 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x22 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x23 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x24 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x25 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x26 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x27 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x28 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x29 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2A { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2B { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2C { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2D { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x49 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4A { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4B { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4C { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4D { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xED { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xFB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xFC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xFF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } default { - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } } @@ -3192,8 +3193,9 @@ object "EvmEmulator" { // GENERAL FUNCTIONS //////////////////////////////////////////////////////////////// - function $llvm_NoInline_llvm$_revert() { - revert(0, 0) + function $llvm_NoInline_llvm$_panic() { // revert consuming all EVM gas + mstore(0, 0) + revert(0, 32) } function revertWithGas(evmGasLeft) { @@ -5665,340 +5667,340 @@ object "EvmEmulator" { } // We explicitly add unused opcodes to optimize the jump table by compiler. case 0x0C { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x0D { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x0E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x0F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x1E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x1F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x21 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x22 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x23 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x24 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x25 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x26 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x27 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x28 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x29 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2A { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2B { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2C { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2D { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x49 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4A { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4B { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4C { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4D { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xED { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xFB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xFC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xFF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } default { - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 7af2ecc82..494ef7540 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -134,8 +134,9 @@ function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 // GENERAL FUNCTIONS //////////////////////////////////////////////////////////////// -function $llvm_NoInline_llvm$_revert() { - revert(0, 0) +function $llvm_NoInline_llvm$_panic() { // revert consuming all EVM gas + mstore(0, 0) + revert(0, 32) } function revertWithGas(evmGasLeft) { diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 920ead471..40d637b99 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -1471,6 +1471,6 @@ for { } true { } { // We explicitly add unused opcodes to optimize the jump table by compiler. default { - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoopUnusedOpcodes.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoopUnusedOpcodes.template.yul index 03c163bdd..a59e4eb58 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoopUnusedOpcodes.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoopUnusedOpcodes.template.yul @@ -1,333 +1,333 @@ case 0x0C { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x0D { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x0E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x0F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x1E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x1F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x21 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x22 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x23 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x24 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x25 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x26 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x27 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x28 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x29 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2A { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2B { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2C { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2D { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x2F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x49 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4A { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4B { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4C { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4D { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4E { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0x4F { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xA9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xAF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xB9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xBF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xC9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xCF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xD9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDD { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xDF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE0 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE1 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE3 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE4 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE5 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xE9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEA { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xED { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEE { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xEF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF2 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF6 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF7 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF8 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xF9 { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xFB { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xFC { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } case 0xFF { // Unused opcode - $llvm_NoInline_llvm$_revert() + $llvm_NoInline_llvm$_panic() } \ No newline at end of file From cf476b12e77ac92dff91d8627fa706e98c34fa4e Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 30 Oct 2024 16:25:50 +0100 Subject: [PATCH 130/183] fix(EVM): Implement resetEVMFrame function (#1051) --- system-contracts/contracts/EvmEmulator.yul | 30 +++++++++++++++++++ system-contracts/contracts/EvmGasManager.yul | 7 +++++ .../EvmEmulatorFunctions.template.yul | 15 ++++++++++ 3 files changed, 52 insertions(+) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index a4b60bb0f..5b30b4b89 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -619,6 +619,14 @@ object "EvmEmulator" { } } + function resetEvmFrame() { + // function resetEvmFrame() + // non-standard selector 0x05 + mstore(0, 0x0500000000000000000000000000000000000000000000000000000000000000) + + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) + } + //////////////////////////////////////////////////////////////// // CALLS FUNCTIONALITY //////////////////////////////////////////////////////////////// @@ -772,6 +780,9 @@ object "EvmEmulator" { ) let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET(), retOffset), retSize) + if iszero(success) { + resetEvmFrame() + } newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success @@ -802,6 +813,9 @@ object "EvmEmulator" { } success := call(ergsToPass, addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + if iszero(success) { + resetEvmFrame() + } } } @@ -1103,6 +1117,7 @@ object "EvmEmulator" { case 0 { addr := 0 gasLeft := _saveReturndataAfterEVMCall(0, 0) + resetEvmFrame() } default { gasLeft, addr := _saveConstructorReturnGas() @@ -3616,6 +3631,14 @@ object "EvmEmulator" { } } + function resetEvmFrame() { + // function resetEvmFrame() + // non-standard selector 0x05 + mstore(0, 0x0500000000000000000000000000000000000000000000000000000000000000) + + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) + } + //////////////////////////////////////////////////////////////// // CALLS FUNCTIONALITY //////////////////////////////////////////////////////////////// @@ -3769,6 +3792,9 @@ object "EvmEmulator" { ) let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET(), retOffset), retSize) + if iszero(success) { + resetEvmFrame() + } newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success @@ -3799,6 +3825,9 @@ object "EvmEmulator" { } success := call(ergsToPass, addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + if iszero(success) { + resetEvmFrame() + } } } @@ -4100,6 +4129,7 @@ object "EvmEmulator" { case 0 { addr := 0 gasLeft := _saveReturndataAfterEVMCall(0, 0) + resetEvmFrame() } default { gasLeft, addr := _saveConstructorReturnGas() diff --git a/system-contracts/contracts/EvmGasManager.yul b/system-contracts/contracts/EvmGasManager.yul index 151680825..bf274eae0 100644 --- a/system-contracts/contracts/EvmGasManager.yul +++ b/system-contracts/contracts/EvmGasManager.yul @@ -231,6 +231,13 @@ object "EvmGasManager" { warmAccount(coinbase()) // and the coinbase too return(0x0, 0x0) } + case 5 { // function resetEVMFrame() + // Reset EVM frame context data + // This method is used by EvmEmulator to clean frame data after failed EVM call. + $llvm_AlwaysInline_llvm$_onlyEvmSystemCall() + + tstore(EVM_AUX_DATA_SLOT(), 0) // mark as consumed (clean it) + } default { revert(0, 0) } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 494ef7540..249f6a01d 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -557,6 +557,14 @@ function consumeEvmFrame() -> passGas, isStatic, callerEVM { } } +function resetEvmFrame() { + // function resetEvmFrame() + // non-standard selector 0x05 + mstore(0, 0x0500000000000000000000000000000000000000000000000000000000000000) + + performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 1) +} + //////////////////////////////////////////////////////////////// // CALLS FUNCTIONALITY //////////////////////////////////////////////////////////////// @@ -710,6 +718,9 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGa ) let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET(), retOffset), retSize) + if iszero(success) { + resetEvmFrame() + } newGasLeft := add(evmGasLeft, frameGasLeft) stackHead := success @@ -740,6 +751,9 @@ function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, r } success := call(ergsToPass, addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + if iszero(success) { + resetEvmFrame() + } } } @@ -1041,6 +1055,7 @@ function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> case 0 { addr := 0 gasLeft := _saveReturndataAfterEVMCall(0, 0) + resetEvmFrame() } default { gasLeft, addr := _saveConstructorReturnGas() From 19a6872b4c3ff33343e30b4fb6c232bfc83c415b Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 30 Oct 2024 16:27:59 +0100 Subject: [PATCH 131/183] fix(EVM): Change gas model (#1047) --- system-contracts/contracts/Constants.sol | 2 - .../contracts/ContractDeployer.sol | 26 ++-- system-contracts/contracts/EvmEmulator.yul | 112 ++++++++---------- .../evm-emulator/EvmEmulator.template.yul | 2 +- .../EvmEmulatorFunctions.template.yul | 55 ++++----- 5 files changed, 78 insertions(+), 119 deletions(-) diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index c77926e2c..545529721 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -164,7 +164,5 @@ uint256 constant BLOB_SIZE_BYTES = 126_976; /// @dev Max number of blobs currently supported uint256 constant MAX_NUMBER_OF_BLOBS = 6; -uint32 constant EVM_GAS_STIPEND = 1 << 30; - uint8 constant ERA_VM_BYTECODE_FLAG = 1; uint8 constant EVM_BYTECODE_FLAG = 2; \ No newline at end of file diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index a8ea69945..bb0b5b5d6 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; 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, SYSTEM_CONTEXT_CONTRACT, EVM_GAS_STIPEND} 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, SYSTEM_CONTEXT_CONTRACT} from "./Constants.sol"; import {Utils} from "./libraries/Utils.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; @@ -191,7 +191,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); - _evmDeployOnAddress(uint32(gasleft()), msg.sender, newAddress, _initCode); + _evmDeployOnAddress(msg.sender, newAddress, _initCode); return newAddress; } @@ -209,7 +209,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { bytes32 bytecodeHash = EfficientCall.keccak(_initCode); address newAddress = Utils.getNewAddressCreate2EVM(msg.sender, _salt, bytecodeHash); - _evmDeployOnAddress(uint32(gasleft()), msg.sender, newAddress, _initCode); + _evmDeployOnAddress(msg.sender, newAddress, _initCode); return newAddress; } @@ -245,15 +245,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address newAddress, bytes calldata _initCode ) external payable onlySystemCallFromEvmEmulator returns (uint256, address) { - uint32 providedErgs; - uint32 stipend = EVM_GAS_STIPEND; - assembly { - let _gas := gas() - if gt(_gas, stipend) { - providedErgs := sub(_gas, stipend) - } - } - uint256 constructorReturnEvmGas = _evmDeployOnAddress(providedErgs, msg.sender, newAddress, _initCode); + uint256 constructorReturnEvmGas = _evmDeployOnAddress(msg.sender, newAddress, _initCode); return (constructorReturnEvmGas, newAddress); } @@ -415,7 +407,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } function _evmDeployOnAddress( - uint32 _gasToPass, address _sender, address _newAddress, bytes calldata _initCode @@ -427,7 +418,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); - return _performDeployOnAddressEVM(_gasToPass, _sender, _newAddress, AccountAbstractionVersion.None, _initCode); + return _performDeployOnAddressEVM(_sender, _newAddress, AccountAbstractionVersion.None, _initCode); } /// @notice Deploy a certain bytecode on the address. @@ -461,13 +452,11 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } /// @notice Deploy a certain bytecode on the address. - /// @param _gasToPass The amount of gas to be passed in constructor /// @param _sender The deployer 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( - uint32 _gasToPass, address _sender, address _newAddress, AccountAbstractionVersion _aaVersion, @@ -483,7 +472,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(_newAddress); // We will store dummy constructing bytecode hash to trigger EVM emulator in constructor call - return _constructEVMContract(_gasToPass, _sender, _newAddress, _input); + return _constructEVMContract(_sender, _newAddress, _input); } /// @notice Check that bytecode hash is marked as known on the `KnownCodeStorage` system contracts @@ -556,7 +545,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } function _constructEVMContract( - uint32 gasToPass, address _sender, address _newAddress, bytes calldata _input @@ -582,7 +570,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } bytes memory paddedBytecode = EfficientCall.mimicCall({ - _gas: gasToPass, // ergs, not EVM gas + _gas: gasleft(), // note: native gas, not EVM gas _address: _newAddress, _data: _input, _whoToMimic: _sender, diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 5b30b4b89..b793ca3f8 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -178,8 +178,6 @@ object "EvmEmulator" { // 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 - // We need to pass some gas for MsgValueSimulator internal logic to decommit emulator etc function MSG_VALUE_SIMULATOR_STIPEND_GAS() -> gas_stipend { gas_stipend := 35000 // 27000 + a little bit more @@ -196,6 +194,11 @@ object "EvmEmulator" { // GENERAL FUNCTIONS //////////////////////////////////////////////////////////////// + // abort the whole EVM execution environment, including parent frames + function abortEvmEnvironment() { + revert(0, 0) + } + function $llvm_NoInline_llvm$_panic() { // revert consuming all EVM gas mstore(0, 0) revert(0, 32) @@ -226,18 +229,9 @@ object "EvmEmulator" { function getEvmGasFromContext() -> evmGas { // Caller must pass at least OVERHEAD() ergs - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) - - let _gas := gas() - if gt(_gas, requiredGas) { - evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) - } - } - - function providedErgs() -> ergs { let _gas := gas() - if gt(_gas, EVM_GAS_STIPEND()) { - ergs := sub(_gas, EVM_GAS_STIPEND()) + if gt(_gas, OVERHEAD()) { + evmGas := div(sub(_gas, OVERHEAD()), GAS_DIVISOR()) } } @@ -350,7 +344,7 @@ object "EvmEmulator" { if iszero(success) { // This error should never happen - revert(0, 0) + abortEvmEnvironment() } returndatacopy(0, 0, 32) @@ -443,7 +437,7 @@ object "EvmEmulator" { if iszero(success) { // This error should never happen - revert(0, 0) + abortEvmEnvironment() } } @@ -568,7 +562,7 @@ object "EvmEmulator" { if iszero(success) { // This error should never happen - revert(0, 0) + abortEvmEnvironment() } if returndatasize() { @@ -771,7 +765,7 @@ object "EvmEmulator" { pushEvmFrame(gasToPass, isStatic) let success := delegatecall( - providedErgs(), + gas(), // pass all remaining native gas addr, add(MEM_OFFSET(), argsOffset), argsSize, @@ -805,13 +799,8 @@ object "EvmEmulator" { } default { pushEvmFrame(gasToPass, isStatic) - // VM will add EVM_GAS_STIPEND() to gas for this call, but if value != 0 we will firstly call MsgValueSimulator contract - // which is zkVM system contract. So we need to add some gas for MsgValueSimulator - let ergsToPass := providedErgs() - if value { - ergsToPass := add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), ergsToPass) - } - success := call(ergsToPass, addr, value, argsOffset, argsSize, 0, 0) + // pass all remaining native gas + success := call(gas(), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) if iszero(success) { resetEvmFrame() @@ -968,8 +957,8 @@ object "EvmEmulator" { switch gt(rtsz, 31) case 0 { // Unexpected return data. - _gasLeft := 0 - _eraseReturndataPointer() + // Most likely out-of-ergs or unexpected error in the emulator or system contracts + abortEvmEnvironment() } default { returndatacopy(0, 0, 32) @@ -1150,13 +1139,15 @@ object "EvmEmulator" { function _saveConstructorReturnGas() -> gasLeft, addr { loadReturndataIntoActivePtr() - if gt(returndatasize(), 63) { // >= 64 - // ContractDeployer returns (uint256 gasLeft, address createdContract) - returndatacopy(0, 0, 64) - gasLeft := mload(0) - addr := mload(32) + if lt(returndatasize(), 64) { + // unexpected return data after constructor succeeded, should never happen. + abortEvmEnvironment() } - // else: unexpected return data after constructor succeeded, should never happen. + + // ContractDeployer returns (uint256 gasLeft, address createdContract) + returndatacopy(0, 0, 64) + gasLeft := mload(0) + addr := mload(32) _eraseReturndataPointer() } @@ -3035,7 +3026,7 @@ object "EvmEmulator" { let evmGasLeft, isStatic, isCallerEVM := consumeEvmFrame() if isStatic { - revert(0, 0) + abortEvmEnvironment() // should never happen } getConstructorBytecode() @@ -3190,8 +3181,6 @@ object "EvmEmulator" { // 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 - // We need to pass some gas for MsgValueSimulator internal logic to decommit emulator etc function MSG_VALUE_SIMULATOR_STIPEND_GAS() -> gas_stipend { gas_stipend := 35000 // 27000 + a little bit more @@ -3208,6 +3197,11 @@ object "EvmEmulator" { // GENERAL FUNCTIONS //////////////////////////////////////////////////////////////// + // abort the whole EVM execution environment, including parent frames + function abortEvmEnvironment() { + revert(0, 0) + } + function $llvm_NoInline_llvm$_panic() { // revert consuming all EVM gas mstore(0, 0) revert(0, 32) @@ -3238,18 +3232,9 @@ object "EvmEmulator" { function getEvmGasFromContext() -> evmGas { // Caller must pass at least OVERHEAD() ergs - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) - let _gas := gas() - if gt(_gas, requiredGas) { - evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) - } - } - - function providedErgs() -> ergs { - let _gas := gas() - if gt(_gas, EVM_GAS_STIPEND()) { - ergs := sub(_gas, EVM_GAS_STIPEND()) + if gt(_gas, OVERHEAD()) { + evmGas := div(sub(_gas, OVERHEAD()), GAS_DIVISOR()) } } @@ -3362,7 +3347,7 @@ object "EvmEmulator" { if iszero(success) { // This error should never happen - revert(0, 0) + abortEvmEnvironment() } returndatacopy(0, 0, 32) @@ -3455,7 +3440,7 @@ object "EvmEmulator" { if iszero(success) { // This error should never happen - revert(0, 0) + abortEvmEnvironment() } } @@ -3580,7 +3565,7 @@ object "EvmEmulator" { if iszero(success) { // This error should never happen - revert(0, 0) + abortEvmEnvironment() } if returndatasize() { @@ -3783,7 +3768,7 @@ object "EvmEmulator" { pushEvmFrame(gasToPass, isStatic) let success := delegatecall( - providedErgs(), + gas(), // pass all remaining native gas addr, add(MEM_OFFSET(), argsOffset), argsSize, @@ -3817,13 +3802,8 @@ object "EvmEmulator" { } default { pushEvmFrame(gasToPass, isStatic) - // VM will add EVM_GAS_STIPEND() to gas for this call, but if value != 0 we will firstly call MsgValueSimulator contract - // which is zkVM system contract. So we need to add some gas for MsgValueSimulator - let ergsToPass := providedErgs() - if value { - ergsToPass := add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), ergsToPass) - } - success := call(ergsToPass, addr, value, argsOffset, argsSize, 0, 0) + // pass all remaining native gas + success := call(gas(), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) if iszero(success) { resetEvmFrame() @@ -3980,8 +3960,8 @@ object "EvmEmulator" { switch gt(rtsz, 31) case 0 { // Unexpected return data. - _gasLeft := 0 - _eraseReturndataPointer() + // Most likely out-of-ergs or unexpected error in the emulator or system contracts + abortEvmEnvironment() } default { returndatacopy(0, 0, 32) @@ -4162,13 +4142,15 @@ object "EvmEmulator" { function _saveConstructorReturnGas() -> gasLeft, addr { loadReturndataIntoActivePtr() - if gt(returndatasize(), 63) { // >= 64 - // ContractDeployer returns (uint256 gasLeft, address createdContract) - returndatacopy(0, 0, 64) - gasLeft := mload(0) - addr := mload(32) + if lt(returndatasize(), 64) { + // unexpected return data after constructor succeeded, should never happen. + abortEvmEnvironment() } - // else: unexpected return data after constructor succeeded, should never happen. + + // ContractDeployer returns (uint256 gasLeft, address createdContract) + returndatacopy(0, 0, 64) + gasLeft := mload(0) + addr := mload(32) _eraseReturndataPointer() } diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index 5f4c2a0dd..247cfd786 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -85,7 +85,7 @@ object "EvmEmulator" { let evmGasLeft, isStatic, isCallerEVM := consumeEvmFrame() if isStatic { - revert(0, 0) + abortEvmEnvironment() // should never happen } getConstructorBytecode() diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 249f6a01d..968d5ad64 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -116,8 +116,6 @@ function MAX_UINT() -> max_uint { // 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 - // We need to pass some gas for MsgValueSimulator internal logic to decommit emulator etc function MSG_VALUE_SIMULATOR_STIPEND_GAS() -> gas_stipend { gas_stipend := 35000 // 27000 + a little bit more @@ -134,6 +132,11 @@ function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 // GENERAL FUNCTIONS //////////////////////////////////////////////////////////////// +// abort the whole EVM execution environment, including parent frames +function abortEvmEnvironment() { + revert(0, 0) +} + function $llvm_NoInline_llvm$_panic() { // revert consuming all EVM gas mstore(0, 0) revert(0, 32) @@ -164,18 +167,9 @@ function chargeGas(prevGas, toCharge) -> gasRemaining { function getEvmGasFromContext() -> evmGas { // Caller must pass at least OVERHEAD() ergs - let requiredGas := add(EVM_GAS_STIPEND(), OVERHEAD()) - - let _gas := gas() - if gt(_gas, requiredGas) { - evmGas := div(sub(_gas, requiredGas), GAS_DIVISOR()) - } -} - -function providedErgs() -> ergs { let _gas := gas() - if gt(_gas, EVM_GAS_STIPEND()) { - ergs := sub(_gas, EVM_GAS_STIPEND()) + if gt(_gas, OVERHEAD()) { + evmGas := div(sub(_gas, OVERHEAD()), GAS_DIVISOR()) } } @@ -288,7 +282,7 @@ function fetchFromSystemContract(to, argSize) -> res { if iszero(success) { // This error should never happen - revert(0, 0) + abortEvmEnvironment() } returndatacopy(0, 0, 32) @@ -381,7 +375,7 @@ function performSystemCall(to, dataLength) { if iszero(success) { // This error should never happen - revert(0, 0) + abortEvmEnvironment() } } @@ -506,7 +500,7 @@ function isSlotWarm(key) -> isWarm { if iszero(success) { // This error should never happen - revert(0, 0) + abortEvmEnvironment() } if returndatasize() { @@ -709,7 +703,7 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGa pushEvmFrame(gasToPass, isStatic) let success := delegatecall( - providedErgs(), + gas(), // pass all remaining native gas addr, add(MEM_OFFSET(), argsOffset), argsSize, @@ -743,13 +737,8 @@ function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, r } default { pushEvmFrame(gasToPass, isStatic) - // VM will add EVM_GAS_STIPEND() to gas for this call, but if value != 0 we will firstly call MsgValueSimulator contract - // which is zkVM system contract. So we need to add some gas for MsgValueSimulator - let ergsToPass := providedErgs() - if value { - ergsToPass := add(MSG_VALUE_SIMULATOR_STIPEND_GAS(), ergsToPass) - } - success := call(ergsToPass, addr, value, argsOffset, argsSize, 0, 0) + // pass all remaining native gas + success := call(gas(), addr, value, argsOffset, argsSize, 0, 0) frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) if iszero(success) { resetEvmFrame() @@ -906,8 +895,8 @@ function _saveReturndataAfterEVMCall(_outputOffset, _outputLen) -> _gasLeft { switch gt(rtsz, 31) case 0 { // Unexpected return data. - _gasLeft := 0 - _eraseReturndataPointer() + // Most likely out-of-ergs or unexpected error in the emulator or system contracts + abortEvmEnvironment() } default { returndatacopy(0, 0, 32) @@ -1088,13 +1077,15 @@ function performSystemCallForCreate(value, bytecodeStart, bytecodeLen) -> succes function _saveConstructorReturnGas() -> gasLeft, addr { loadReturndataIntoActivePtr() - if gt(returndatasize(), 63) { // >= 64 - // ContractDeployer returns (uint256 gasLeft, address createdContract) - returndatacopy(0, 0, 64) - gasLeft := mload(0) - addr := mload(32) + if lt(returndatasize(), 64) { + // unexpected return data after constructor succeeded, should never happen. + abortEvmEnvironment() } - // else: unexpected return data after constructor succeeded, should never happen. + + // ContractDeployer returns (uint256 gasLeft, address createdContract) + returndatacopy(0, 0, 64) + gasLeft := mload(0) + addr := mload(32) _eraseReturndataPointer() } From 7a4a895cd425abca1c933b786063d6cefe28dedd Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 30 Oct 2024 16:35:18 +0100 Subject: [PATCH 132/183] feat(EVM): Optimize extcodecopy (#1046) --- system-contracts/contracts/EvmEmulator.yul | 54 ++++++++++++++----- .../EvmEmulatorFunctions.template.yul | 4 ++ .../evm-emulator/EvmEmulatorLoop.template.yul | 23 +++++--- 3 files changed, 60 insertions(+), 21 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index b793ca3f8..a00e362a4 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -175,6 +175,10 @@ object "EvmEmulator" { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } + function MAX_UINT64() -> max { + max := sub(shl(64, 1), 1) + } + // Each evm gas is 5 zkEVM one function GAS_DIVISOR() -> gas_div { gas_div := 5 } @@ -1662,14 +1666,23 @@ object "EvmEmulator" { } evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - - $llvm_AlwaysInline_llvm$_memsetToZero(dstOffset, len) - - // Gets the code from the addr - if and(iszero(iszero(getRawCodeHash(addr))), gt(len, 0)) { - pop(fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) - } + if gt(srcOffset, MAX_UINT64()) { + srcOffset := MAX_UINT64() + } + + if gt(len, 0) { + let realCodeLen + if getRawCodeHash(addr) { + // Gets the code from the addr + realCodeLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) + } + + if lt(realCodeLen, len) { + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, realCodeLen), sub(len, realCodeLen)) + } + } + ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE @@ -3178,6 +3191,10 @@ object "EvmEmulator" { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } + function MAX_UINT64() -> max { + max := sub(shl(64, 1), 1) + } + // Each evm gas is 5 zkEVM one function GAS_DIVISOR() -> gas_div { gas_div := 5 } @@ -4665,14 +4682,23 @@ object "EvmEmulator" { } evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - - $llvm_AlwaysInline_llvm$_memsetToZero(dstOffset, len) - - // Gets the code from the addr - if and(iszero(iszero(getRawCodeHash(addr))), gt(len, 0)) { - pop(fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) - } + if gt(srcOffset, MAX_UINT64()) { + srcOffset := MAX_UINT64() + } + + if gt(len, 0) { + let realCodeLen + if getRawCodeHash(addr) { + // Gets the code from the addr + realCodeLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) + } + + if lt(realCodeLen, len) { + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, realCodeLen), sub(len, realCodeLen)) + } + } + ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 968d5ad64..efe6def0d 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -113,6 +113,10 @@ function MAX_UINT() -> max_uint { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } +function MAX_UINT64() -> max { + max := sub(shl(64, 1), 1) +} + // Each evm gas is 5 zkEVM one function GAS_DIVISOR() -> gas_div { gas_div := 5 } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 40d637b99..b2ae62199 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -456,14 +456,23 @@ for { } true { } { } evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - - $llvm_AlwaysInline_llvm$_memsetToZero(dstOffset, len) - - // Gets the code from the addr - if and(iszero(iszero(getRawCodeHash(addr))), gt(len, 0)) { - pop(fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)) - } + if gt(srcOffset, MAX_UINT64()) { + srcOffset := MAX_UINT64() + } + + if gt(len, 0) { + let realCodeLen + if getRawCodeHash(addr) { + // Gets the code from the addr + realCodeLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) + } + + if lt(realCodeLen, len) { + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, realCodeLen), sub(len, realCodeLen)) + } + } + ip := add(ip, 1) } case 0x3D { // OP_RETURNDATASIZE From 397092db593baa5003ec77ad420c50104bc02fe2 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 30 Oct 2024 17:25:28 +0100 Subject: [PATCH 133/183] fix(EVM): Fix data copy corner cases (#1053) --- system-contracts/SystemContractsHashes.json | 40 +++--- system-contracts/contracts/EvmEmulator.yul | 116 ++++++++++++++---- .../EvmEmulatorFunctions.template.yul | 23 +++- .../evm-emulator/EvmEmulatorLoop.template.yul | 35 ++++-- 4 files changed, 155 insertions(+), 59 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 442620f48..a1ee58c12 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": "0x0100007757f0a993c2b61e4b7b980eac7c16f9461d56b872befad11edf1791ef", + "bytecodeHash": "0x01000077e38f3e974a8def22f43e6c3c566d7c18ba04a55dfbad90dfd972920b", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f1164848f2e7669df28198a273458ba1fdf1ed0a04321289821d624ad4", + "bytecodeHash": "0x010006f1264905c7690fec8739ef464fb0efe1b6a2b3d1ef9c8bc31021c2d3eb", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004772c49529c6ccb5f6b3b1ea23d7498a172b59f3aa8797443ab7ec423a", + "bytecodeHash": "0x0100004781f95009a16d912d2bf05573968ed0897b590791129e5c8cd6a66257", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013f346ef598ecf8a5ba86e2fa4b306816a89a5a96af611047f3508faf03", + "bytecodeHash": "0x0100013f94deb4d671b1f75987670fe3f875e0730aee2e4ae44d75f147201e38", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x01000671f7ed086cc23329dd16d7e240c19b1a96c6571728c762f705f7c5549b", - "sourceCodeHash": "0x86897736464a0363c5b13c1d5796bfc6ba37e6eaadb848ed13ab69e54b16f21a" + "bytecodeHash": "0x0100067112f5b7b010c31dc21efe07f983df32f1908a48bd7084e8c967f19470", + "sourceCodeHash": "0x3a03e66288c63fb72abe909ae829fa9495dce051753687d4395d41971847826b" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003fc7635b13ed69e2a8e85908317afa68eee660998372981c7ca9991aaa", + "bytecodeHash": "0x0100003f93af5076860d7d80073c61d1f81a2b41b685d139f17320e337dc204c", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x010005096489d3a6c7c9d18750a4bda0f78c7a7f71ec540cb9b0fb8f2970922b", + "bytecodeHash": "0x0100050989d91484a0d994fab1527c01f1f5fa39c9993945ae943874c4667e7d", "sourceCodeHash": "0xef448fac6b6f1c217b6495ee134a3553e02dfb920fd46bc71de33672e64d9ab8" }, { @@ -59,56 +59,56 @@ "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x010000333575bcc1f34a79d1b43bb8f69813d35463b602e8e1fb88d85806aee1", + "bytecodeHash": "0x01000033de8aeec22172e554f130cf986fc38c7c2d1fa0021d2197db9043b125", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cdc5734c8109be1afdc5ad40c84157d9f19bc1967d8a128444bcce0360", + "bytecodeHash": "0x010000cdf509accfddca2517ef4a7ef699d898262af5e79f0e7c5c7966f12c6a", "sourceCodeHash": "0x851fb5e170dfde39f1f9bc74654ec0b8f8f1d4c2fb20c06c77844c1e3ee0659a" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000265966dd95109bdd779e6deeb4f531d0cd983fb053ed77fbb982f94607b", + "bytecodeHash": "0x010002659014fddc66937d91a9a4b149568ad0c7f6c3797ae7d5bd2a8ddd7877", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f33e4c891018536ca207056f7536854b030d847fdd7f21eb5576b30ed4", + "bytecodeHash": "0x010000f3e13f08f85a3271fb8bc1bf70364933b63e9d7025f722d98bc589e9d0", "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x01000059700408fe641af24437be3a197adfa4798b943594dc83f10a70bae855", + "bytecodeHash": "0x0100005978b4f9317489d511739a80bedb832092c8741a45ed636de64167aca0", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cffce37e7325318c746f5af8bd8d5f22236eabe2c5c78fc2acca5b418d", + "bytecodeHash": "0x010000cfa3b3ba69935156cb43bc4501fef0897c657dd0e5574064cad3243df0", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041a25a3ab6180cb1d752e742d9e39c8637b6c9e1e64a52d002f761b32d", + "bytecodeHash": "0x01000041332bbd6c2abad4bc30bb3d9a9a26d914c11e4bcc803cd0905eaff964", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c56a15564c7f07cc0dc68099436b1b40110f2d011b957860e324f948d7", + "bytecodeHash": "0x010001c5415782e13f8c4026d2b1e3270b4c5ef92fb9fe731ff2a3c1ada12601", "sourceCodeHash": "0xe2f6eb015d260aafe9405b28ef3ec27921add4de7f329b7ef61e0aa6c9365e29" }, { @@ -122,15 +122,15 @@ "contractName": "EvmEmulator", "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cb54199e828134a56d7302a7ed55ba8f0b54d898aa0f3949ca2774b1643", - "sourceCodeHash": "0xa1ce6b22af5b1be710181ea59b4a76879ccb0d4989d533c92965df1bbaa340b2" + "bytecodeHash": "0x01000cb5ab96098493fa599effb19ce9c6d8db6e9bfe34004ce3ff35e2225a75", + "sourceCodeHash": "0x86296ecb81fc9edf5aac32613dfd645b538535e264e02a12ec7cdc751018de5d" }, { "contractName": "EvmGasManager", "bytecodePath": "contracts-preprocessed/artifacts/EvmGasManager.yul/EvmGasManager.yul.zbin", "sourceCodePath": "contracts-preprocessed/EvmGasManager.yul", - "bytecodeHash": "0x010000697e213955edae21195912d2900639a2eba6d15f592a12bfb05b350966", - "sourceCodeHash": "0x1eb4cffcd8b9365bed383e199ab169af21a8ba809a685c0a36f89a128d8582f8" + "bytecodeHash": "0x01000073f07635332a31f5a0f84ae277e3462b0240ced32b9def9785c67e6a99", + "sourceCodeHash": "0x825dc1d9bec5128457a8b96eaf7ebf7c89dbb95a9bd7aab0f1601bc06455abfb" }, { "contractName": "CodeOracle", diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index a00e362a4..f9a9c0d75 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -393,18 +393,33 @@ object "EvmEmulator" { isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } - // Basically performs an extcodecopy, while returning the length of the bytecode. - function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> codeLen { + // Basically performs an extcodecopy, while returning the length of the copied bytecode. + function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) mstore(0, codeHash) // The first word of returndata is the true length of the bytecode - codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) + let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) if gt(len, codeLen) { len := codeLen } - returndatacopy(dstOffset, add(32, srcOffset), len) + let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length + + let _returndatasize := returndatasize() + if gt(shiftedSrcOffset, _returndatasize) { + shiftedSrcOffset := _returndatasize + } + + if gt(add(len, shiftedSrcOffset), _returndatasize) { + len := sub(_returndatasize, shiftedSrcOffset) + } + + if len { + returndatacopy(dstOffset, shiftedSrcOffset, len) + } + + copiedLen := len } // Returns the length of the EVM bytecode. @@ -1571,6 +1586,10 @@ object "EvmEmulator" { checkMemIsAccessible(destOffset, size) + if gt(offset, MAX_UINT64()) { + offset := MAX_UINT64() + } + // 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(destOffset, size)) @@ -1606,15 +1625,28 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) dstOffset := add(dstOffset, MEM_OFFSET()) + + if gt(sourceOffset, MAX_UINT64()) { + sourceOffset := MAX_UINT64() + } + sourceOffset := add(sourceOffset, BYTECODE_OFFSET()) - checkOverflow(sourceOffset, len) - // Check bytecode overflow - if gt(add(sourceOffset, len), sub(MEM_LEN_OFFSET(), 1)) { - panic() + if gt(sourceOffset, MEM_LEN_OFFSET()) { + sourceOffset := MEM_LEN_OFFSET() } - $llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, len) + // Check bytecode out-of-bounds access + let truncatedLen := len + if gt(add(sourceOffset, len), MEM_LEN_OFFSET()) { + truncatedLen := sub(MEM_LEN_OFFSET(), sourceOffset) // truncate + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, truncatedLen), sub(len, truncatedLen)) // pad with zeroes any out-of-bounds + } + + if truncatedLen { + $llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, truncatedLen) + } + ip := add(ip, 1) } case 0x3A { // OP_GASPRICE @@ -1672,14 +1704,14 @@ object "EvmEmulator" { } if gt(len, 0) { - let realCodeLen + let copiedLen if getRawCodeHash(addr) { // Gets the code from the addr - realCodeLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) + copiedLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) } - if lt(realCodeLen, len) { - $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, realCodeLen), sub(len, realCodeLen)) + if lt(copiedLen, len) { + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, copiedLen), sub(len, copiedLen)) } } @@ -3409,18 +3441,33 @@ object "EvmEmulator" { isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } - // Basically performs an extcodecopy, while returning the length of the bytecode. - function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> codeLen { + // Basically performs an extcodecopy, while returning the length of the copied bytecode. + function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) mstore(0, codeHash) // The first word of returndata is the true length of the bytecode - codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) + let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) if gt(len, codeLen) { len := codeLen } - returndatacopy(dstOffset, add(32, srcOffset), len) + let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length + + let _returndatasize := returndatasize() + if gt(shiftedSrcOffset, _returndatasize) { + shiftedSrcOffset := _returndatasize + } + + if gt(add(len, shiftedSrcOffset), _returndatasize) { + len := sub(_returndatasize, shiftedSrcOffset) + } + + if len { + returndatacopy(dstOffset, shiftedSrcOffset, len) + } + + copiedLen := len } // Returns the length of the EVM bytecode. @@ -4587,6 +4634,10 @@ object "EvmEmulator" { checkMemIsAccessible(destOffset, size) + if gt(offset, MAX_UINT64()) { + offset := MAX_UINT64() + } + // 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(destOffset, size)) @@ -4622,15 +4673,28 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) dstOffset := add(dstOffset, MEM_OFFSET()) + + if gt(sourceOffset, MAX_UINT64()) { + sourceOffset := MAX_UINT64() + } + sourceOffset := add(sourceOffset, BYTECODE_OFFSET()) - checkOverflow(sourceOffset, len) - // Check bytecode overflow - if gt(add(sourceOffset, len), sub(MEM_LEN_OFFSET(), 1)) { - panic() + if gt(sourceOffset, MEM_LEN_OFFSET()) { + sourceOffset := MEM_LEN_OFFSET() } - $llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, len) + // Check bytecode out-of-bounds access + let truncatedLen := len + if gt(add(sourceOffset, len), MEM_LEN_OFFSET()) { + truncatedLen := sub(MEM_LEN_OFFSET(), sourceOffset) // truncate + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, truncatedLen), sub(len, truncatedLen)) // pad with zeroes any out-of-bounds + } + + if truncatedLen { + $llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, truncatedLen) + } + ip := add(ip, 1) } case 0x3A { // OP_GASPRICE @@ -4688,14 +4752,14 @@ object "EvmEmulator" { } if gt(len, 0) { - let realCodeLen + let copiedLen if getRawCodeHash(addr) { // Gets the code from the addr - realCodeLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) + copiedLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) } - if lt(realCodeLen, len) { - $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, realCodeLen), sub(len, realCodeLen)) + if lt(copiedLen, len) { + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, copiedLen), sub(len, copiedLen)) } } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index efe6def0d..58736a58d 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -331,18 +331,33 @@ function isEvmContract(addr) -> isEVM { isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } -// Basically performs an extcodecopy, while returning the length of the bytecode. -function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> codeLen { +// Basically performs an extcodecopy, while returning the length of the copied bytecode. +function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) mstore(0, codeHash) // The first word of returndata is the true length of the bytecode - codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) + let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) if gt(len, codeLen) { len := codeLen } - returndatacopy(dstOffset, add(32, srcOffset), len) + let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length + + let _returndatasize := returndatasize() + if gt(shiftedSrcOffset, _returndatasize) { + shiftedSrcOffset := _returndatasize + } + + if gt(add(len, shiftedSrcOffset), _returndatasize) { + len := sub(_returndatasize, shiftedSrcOffset) + } + + if len { + returndatacopy(dstOffset, shiftedSrcOffset, len) + } + + copiedLen := len } // Returns the length of the EVM bytecode. diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index b2ae62199..78e1a5315 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -361,6 +361,10 @@ for { } true { } { checkMemIsAccessible(destOffset, size) + if gt(offset, MAX_UINT64()) { + offset := MAX_UINT64() + } + // 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(destOffset, size)) @@ -396,15 +400,28 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) dstOffset := add(dstOffset, MEM_OFFSET()) + + if gt(sourceOffset, MAX_UINT64()) { + sourceOffset := MAX_UINT64() + } + sourceOffset := add(sourceOffset, BYTECODE_OFFSET()) - checkOverflow(sourceOffset, len) - // Check bytecode overflow - if gt(add(sourceOffset, len), sub(MEM_LEN_OFFSET(), 1)) { - panic() + if gt(sourceOffset, MEM_LEN_OFFSET()) { + sourceOffset := MEM_LEN_OFFSET() + } + + // Check bytecode out-of-bounds access + let truncatedLen := len + if gt(add(sourceOffset, len), MEM_LEN_OFFSET()) { + truncatedLen := sub(MEM_LEN_OFFSET(), sourceOffset) // truncate + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, truncatedLen), sub(len, truncatedLen)) // pad with zeroes any out-of-bounds } - $llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, len) + if truncatedLen { + $llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, truncatedLen) + } + ip := add(ip, 1) } case 0x3A { // OP_GASPRICE @@ -462,14 +479,14 @@ for { } true { } { } if gt(len, 0) { - let realCodeLen + let copiedLen if getRawCodeHash(addr) { // Gets the code from the addr - realCodeLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) + copiedLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) } - if lt(realCodeLen, len) { - $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, realCodeLen), sub(len, realCodeLen)) + if lt(copiedLen, len) { + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, copiedLen), sub(len, copiedLen)) } } From 42954fdd309fbd9b1896ee067b2587e79022abcd Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 18 Nov 2024 14:06:36 +0100 Subject: [PATCH 134/183] chore(EVM): Suppress sendtransfer zksolc error (#1067) --- system-contracts/foundry.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/system-contracts/foundry.toml b/system-contracts/foundry.toml index a820faa90..cfd793dac 100644 --- a/system-contracts/foundry.toml +++ b/system-contracts/foundry.toml @@ -9,8 +9,7 @@ remappings = [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", ] -suppressedErrors = ["sendtransfer"] [profile.default.zksync] zksolc = "1.5.6" -suppressedErrors = ["sendtransfer"] +suppressed_errors = ["sendtransfer"] From 38a8bb8d0b264134dcdf8f3c717834b514a81f90 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 18 Nov 2024 14:45:58 +0100 Subject: [PATCH 135/183] chore: Tooling fixes in contracts (#1068) --- l1-contracts/deploy-scripts/Utils.sol | 9 +-------- l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol | 6 +++--- system-contracts/foundry.toml | 3 ++- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/l1-contracts/deploy-scripts/Utils.sol b/l1-contracts/deploy-scripts/Utils.sol index ad8c96094..dc96b32b2 100644 --- a/l1-contracts/deploy-scripts/Utils.sol +++ b/l1-contracts/deploy-scripts/Utils.sol @@ -9,7 +9,7 @@ import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {L2TransactionRequestDirect} from "contracts/bridgehub/IBridgehub.sol"; import {IGovernance} from "contracts/governance/IGovernance.sol"; import {Call} from "contracts/governance/Common.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IERC20} from "@openzeppelin/contracts-v4/token/ERC20/IERC20.sol"; import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA} from "contracts/common/Config.sol"; import {L2_DEPLOYER_SYSTEM_CONTRACT_ADDR} from "contracts/common/L2ContractAddresses.sol"; import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; @@ -105,13 +105,6 @@ library Utils { } } - /** - * @dev Returns the bytecode hash of the batch bootloader. - */ - function getBatchBootloaderBytecodeHash() internal view returns (bytes memory) { - return vm.readFile("../system-contracts/bootloader/build/artifacts/proved_batch.yul/proved_batch.yul.zbin"); - } - /** * @dev Returns the bytecode of a given system contract. */ diff --git a/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol index 301bfd2c8..0f2e589f3 100644 --- a/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol +++ b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol @@ -6,8 +6,8 @@ import {stdToml} from "forge-std/StdToml.sol"; import {Utils} from "./../Utils.sol"; import {L1SharedBridge} from "contracts/bridge/L1SharedBridge.sol"; import {DummyL1ERC20Bridge} from "contracts/dev-contracts/DummyL1ERC20Bridge.sol"; -import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; -import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts-v4/proxy/transparent/ProxyAdmin.sol"; +import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol"; import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; /// This scripts is only for developer @@ -122,7 +122,7 @@ contract SetupLegacyBridge is Script { ); bytes memory beaconProxy = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.json" + "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol/BeaconProxy.json" ); (tokenBeaconAddress, tokenBeaconBytecodeHash) = calculateL2Create2Address( diff --git a/system-contracts/foundry.toml b/system-contracts/foundry.toml index 748734ad6..312de073f 100644 --- a/system-contracts/foundry.toml +++ b/system-contracts/foundry.toml @@ -10,4 +10,5 @@ remappings = [ ] [profile.default.zksync] -zksolc = "1.5.4" +zksolc = "1.5.6" +suppressed_errors = ["sendtransfer"] From 7a2f58731f63a2fc87cbcaf1d4445cf6a405874a Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 18 Nov 2024 15:05:42 +0100 Subject: [PATCH 136/183] chore(EVM): Merge dev (#1069) Signed-off-by: Danil Co-authored-by: kelemeno <34402761+kelemeno@users.noreply.github.com> Co-authored-by: Danil Co-authored-by: Vlad Bochok <41153528+vladbochok@users.noreply.github.com> --- l1-contracts/deploy-scripts/Utils.sol | 9 +-------- l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol | 6 +++--- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/l1-contracts/deploy-scripts/Utils.sol b/l1-contracts/deploy-scripts/Utils.sol index ad8c96094..dc96b32b2 100644 --- a/l1-contracts/deploy-scripts/Utils.sol +++ b/l1-contracts/deploy-scripts/Utils.sol @@ -9,7 +9,7 @@ import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {L2TransactionRequestDirect} from "contracts/bridgehub/IBridgehub.sol"; import {IGovernance} from "contracts/governance/IGovernance.sol"; import {Call} from "contracts/governance/Common.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IERC20} from "@openzeppelin/contracts-v4/token/ERC20/IERC20.sol"; import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA} from "contracts/common/Config.sol"; import {L2_DEPLOYER_SYSTEM_CONTRACT_ADDR} from "contracts/common/L2ContractAddresses.sol"; import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; @@ -105,13 +105,6 @@ library Utils { } } - /** - * @dev Returns the bytecode hash of the batch bootloader. - */ - function getBatchBootloaderBytecodeHash() internal view returns (bytes memory) { - return vm.readFile("../system-contracts/bootloader/build/artifacts/proved_batch.yul/proved_batch.yul.zbin"); - } - /** * @dev Returns the bytecode of a given system contract. */ diff --git a/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol index 301bfd2c8..0f2e589f3 100644 --- a/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol +++ b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol @@ -6,8 +6,8 @@ import {stdToml} from "forge-std/StdToml.sol"; import {Utils} from "./../Utils.sol"; import {L1SharedBridge} from "contracts/bridge/L1SharedBridge.sol"; import {DummyL1ERC20Bridge} from "contracts/dev-contracts/DummyL1ERC20Bridge.sol"; -import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; -import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts-v4/proxy/transparent/ProxyAdmin.sol"; +import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol"; import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; /// This scripts is only for developer @@ -122,7 +122,7 @@ contract SetupLegacyBridge is Script { ); bytes memory beaconProxy = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol/BeaconProxy.json" + "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol/BeaconProxy.json" ); (tokenBeaconAddress, tokenBeaconBytecodeHash) = calculateL2Create2Address( From df328caeb55f514f70f6fed35c239cf168019268 Mon Sep 17 00:00:00 2001 From: koloz193 Date: Tue, 19 Nov 2024 19:16:05 +0700 Subject: [PATCH 137/183] merge release v25 into dev (#1072) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Danil Co-authored-by: Danil Co-authored-by: Vlad Bochok <41153528+vladbochok@users.noreply.github.com> Co-authored-by: Grzegorz Prusak Co-authored-by: Bence Haromi <56651250+benceharomi@users.noreply.github.com> Co-authored-by: Moshe Shababo <17073733+moshababo@users.noreply.github.com> Co-authored-by: Akosh Farkash Co-authored-by: Bruno França Co-authored-by: Roman Brodetski Co-authored-by: vladbochok Co-authored-by: Stanislav Bezkorovainyi Co-authored-by: otani Co-authored-by: Ivan Schasny Co-authored-by: Ivan Schasny <31857042+ischasny@users.noreply.github.com> Co-authored-by: Vladislav Volosnikov --- .github/workflows/build-release.yaml | 30 +- .github/workflows/l1-contracts-ci.yaml | 58 ++-- .github/workflows/l2-contracts-ci.yaml | 34 ++- .github/workflows/slither.yaml | 13 +- .github/workflows/system-contracts-ci.yaml | 66 ++--- .solhintignore | 1 + .../contracts/bridge/L1SharedBridge.sol | 22 +- .../contracts/common/L1ContractErrors.sol | 4 + .../governance/AccessControlRestriction.sol | 72 ----- .../contracts/governance/ChainAdmin.sol | 114 +++----- .../governance/IAccessControlRestriction.sol | 14 - .../contracts/governance/IChainAdmin.sol | 39 ++- .../governance/IPermanentRestriction.sol | 17 -- .../contracts/governance/IRestriction.sol | 15 - .../governance/PermanentRestriction.sol | 186 ------------- .../ChainConfigurationReader.s.sol | 63 +++++ l1-contracts/deploy-scripts/DeployErc20.s.sol | 2 +- l1-contracts/deploy-scripts/DeployL1.s.sol | 4 + .../deploy-scripts/DeployL2Contracts.sol | 99 +++++-- l1-contracts/deploy-scripts/EIP712Utils.sol | 30 ++ .../PrepareZKChainRegistrationCalldata.s.sol | 35 ++- .../deploy-scripts/RegisterHyperchain.s.sol | 35 +-- l1-contracts/deploy-scripts/Utils.sol | 143 ++++++++++ .../dev/SetupLegacyBridge.s.sol | 16 +- .../interfaces/IEmergencyUpgrageBoard.sol | 23 ++ .../deploy-scripts/interfaces/IMultisig.sol | 9 + .../interfaces/IProtocolUpgradeHandler.sol | 33 +++ .../deploy-scripts/interfaces/ISafe.sol | 9 + l1-contracts/script-config/.gitkeep | 0 .../script-config/artifacts/BeaconProxy.json | 81 ------ .../artifacts/L2SharedBridge.json | 262 ------------------ .../TransparentUpgradeableProxy.json | 86 ------ l1-contracts/src.ts/deploy.ts | 14 +- .../Bridgehub/experimental_bridge.t.sol | 6 +- .../Governance/AccessControlRestriction.t.sol | 186 ------------- .../governance/Governance/ChainAdmin.t.sol | 126 ++------- .../Governance/PermanentRestriction.t.sol | 209 -------------- .../test/test_config/constant/hardhat.json | 32 +-- .../dev-contracts/DevL2SharedBridge.sol | 2 +- .../dev-contracts/ITimestampAsserter.sol | 6 + .../contracts/dev-contracts/Multicall3.sol | 237 ++++++++++++++++ .../dev-contracts/TimestampAsserter.sol | 20 ++ l2-contracts/foundry.toml | 2 +- system-contracts/foundry.toml | 1 + system-contracts/scripts/calculate-hashes.ts | 8 +- .../scripts/preprocess-bootloader.ts | 34 ++- 46 files changed, 963 insertions(+), 1535 deletions(-) delete mode 100644 l1-contracts/contracts/governance/AccessControlRestriction.sol delete mode 100644 l1-contracts/contracts/governance/IAccessControlRestriction.sol delete mode 100644 l1-contracts/contracts/governance/IPermanentRestriction.sol delete mode 100644 l1-contracts/contracts/governance/IRestriction.sol delete mode 100644 l1-contracts/contracts/governance/PermanentRestriction.sol create mode 100644 l1-contracts/deploy-scripts/ChainConfigurationReader.s.sol create mode 100644 l1-contracts/deploy-scripts/EIP712Utils.sol create mode 100644 l1-contracts/deploy-scripts/interfaces/IEmergencyUpgrageBoard.sol create mode 100644 l1-contracts/deploy-scripts/interfaces/IMultisig.sol create mode 100644 l1-contracts/deploy-scripts/interfaces/IProtocolUpgradeHandler.sol create mode 100644 l1-contracts/deploy-scripts/interfaces/ISafe.sol create mode 100644 l1-contracts/script-config/.gitkeep delete mode 100644 l1-contracts/script-config/artifacts/BeaconProxy.json delete mode 100644 l1-contracts/script-config/artifacts/L2SharedBridge.json delete mode 100644 l1-contracts/script-config/artifacts/TransparentUpgradeableProxy.json delete mode 100644 l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol delete mode 100644 l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol create mode 100644 l2-contracts/contracts/dev-contracts/ITimestampAsserter.sol create mode 100644 l2-contracts/contracts/dev-contracts/Multicall3.sol create mode 100644 l2-contracts/contracts/dev-contracts/TimestampAsserter.sol diff --git a/.github/workflows/build-release.yaml b/.github/workflows/build-release.yaml index 2335b74fb..b4292e5e3 100644 --- a/.github/workflows/build-release.yaml +++ b/.github/workflows/build-release.yaml @@ -22,6 +22,15 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ inputs.commit }} + submodules: recursive + + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH - name: Use Node.js uses: actions/setup-node@v3 @@ -35,11 +44,24 @@ jobs: yarn echo "release_tag=${{ inputs.prefix }}-${{ inputs.commit }}" >> $GITHUB_OUTPUT - - name: Build contracts + - name: Build l1 contracts + working-directory: l1-contracts + run: | + forge build + + - name: Build l2 contracts + working-directory: l2-contracts + run: | + forge build --zksync --zk-enable-eravm-extensions + + - name: Build system-contracts + working-directory: system-contracts run: | - yarn l1 build - yarn l2 build - yarn sc build + yarn install + yarn preprocess:system-contracts + forge build --zksync --zk-enable-eravm-extensions + yarn preprocess:bootloader + forge build --zksync --zk-enable-eravm-extensions - name: Prepare artifacts run: | diff --git a/.github/workflows/l1-contracts-ci.yaml b/.github/workflows/l1-contracts-ci.yaml index fbf3cc770..5a27c65f8 100644 --- a/.github/workflows/l1-contracts-ci.yaml +++ b/.github/workflows/l1-contracts-ci.yaml @@ -15,6 +15,16 @@ jobs: steps: - name: Checkout the repository uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH - name: Use Node.js uses: actions/setup-node@v3 @@ -22,26 +32,25 @@ jobs: node-version: 18.18.0 cache: yarn - - name: Install dependencies - run: yarn - - - name: Build artifacts - run: yarn l1 build + - name: Build l1 contracts + working-directory: l1-contracts + run: | + forge build - - name: Build L2 artifacts - run: yarn l2 build + - name: Build l2 contracts + working-directory: l2-contracts + run: | + forge build --zksync --zk-enable-eravm-extensions - name: Create cache uses: actions/cache/save@v3 with: key: artifacts-l1-${{ github.sha }} path: | - l1-contracts/artifacts - l1-contracts/cache - l1-contracts/typechain - l2-contracts/artifacts-zk - l2-contracts/cache-zk - l2-contracts/typechain + l1-contracts/cache-forge + l1-contracts/out + l2-contracts/cache-forge + l2-contracts/zkout lint: runs-on: ubuntu-latest @@ -72,15 +81,19 @@ jobs: with: submodules: recursive - - name: Use Foundry - uses: foundry-rs/foundry-toolchain@v1 - - name: Use Node.js uses: actions/setup-node@v3 with: node-version: 18.18.0 cache: yarn + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH - name: Install dependencies run: yarn @@ -128,7 +141,7 @@ jobs: l2-contracts/typechain - name: Run tests - run: yarn l1 test --no-compile + run: yarn l1 test check-verifier-generator: runs-on: ubuntu-latest @@ -164,15 +177,20 @@ jobs: with: submodules: recursive - - name: Use Foundry - uses: foundry-rs/foundry-toolchain@v1 - - name: Use Node.js uses: actions/setup-node@v3 with: node-version: 18.18.0 cache: yarn + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH + - name: Install dependencies run: yarn diff --git a/.github/workflows/l2-contracts-ci.yaml b/.github/workflows/l2-contracts-ci.yaml index 20bb9583f..e19ac376b 100644 --- a/.github/workflows/l2-contracts-ci.yaml +++ b/.github/workflows/l2-contracts-ci.yaml @@ -10,6 +10,16 @@ jobs: steps: - name: Checkout the repository uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH - name: Use Node.js uses: actions/setup-node@v3 @@ -20,23 +30,25 @@ jobs: - name: Install dependencies run: yarn - - name: Build L1 artifacts - run: yarn l1 build + - name: Build l1 contracts + working-directory: l1-contracts + run: | + forge build - - name: Build L2 artifacts - run: yarn l2 build + - name: Build l2 contracts + working-directory: l2-contracts + run: | + forge build --zksync --zk-enable-eravm-extensions - name: Create cache uses: actions/cache/save@v3 with: - key: artifacts-l2-${{ github.sha }} + key: artifacts-l1-${{ github.sha }} path: | - l1-contracts/artifacts - l1-contracts/cache - l1-contracts/typechain - l2-contracts/artifacts-zk - l2-contracts/cache-zk - l2-contracts/typechain + l1-contracts/cache-forge + l1-contracts/out + l2-contracts/cache-forge + l2-contracts/zkout lint: runs-on: ubuntu-latest diff --git a/.github/workflows/slither.yaml b/.github/workflows/slither.yaml index fa253e159..50c9194dc 100644 --- a/.github/workflows/slither.yaml +++ b/.github/workflows/slither.yaml @@ -27,13 +27,18 @@ jobs: with: python-version: 3.8 + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH + - name: Install Slither run: | pip install slither-analyzer - - name: Use Foundry - uses: foundry-rs/foundry-toolchain@v1 - - name: Remove non-compiled files run: | rm -rf ./l1-contracts/contracts/state-transition/utils/ @@ -43,6 +48,6 @@ jobs: rm -rf ./l1-contracts/contracts/dev-contracts/test/VerifierRecursiveTest.sol - name: Run Slither + working-directory: l1-contracts run: | - cd l1-contracts slither --config ./slither.config.json . diff --git a/.github/workflows/system-contracts-ci.yaml b/.github/workflows/system-contracts-ci.yaml index 98d005a35..cf6b984c0 100644 --- a/.github/workflows/system-contracts-ci.yaml +++ b/.github/workflows/system-contracts-ci.yaml @@ -10,6 +10,16 @@ jobs: steps: - name: Checkout the repository uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH - name: Use Node.js uses: actions/setup-node@v3 @@ -17,22 +27,28 @@ jobs: node-version: 18.18.0 cache: yarn - - name: Install dependencies - run: yarn - - name: Build artifacts - run: yarn sc build + working-directory: system-contracts + run: | + yarn install + yarn preprocess:system-contracts + forge build --zksync --zk-enable-eravm-extensions + yarn preprocess:bootloader + forge build --zksync --zk-enable-eravm-extensions + yarn build - name: Create cache uses: actions/cache/save@v3 with: key: artifacts-system-${{ github.sha }} path: | + system-contracts/zkout + system-contracts/cache-forge + system-contracts/bootloader/build system-contracts/artifacts-zk system-contracts/cache-zk system-contracts/typechain system-contracts/contracts-preprocessed - system-contracts/bootloader/build lint: runs-on: ubuntu-latest @@ -72,11 +88,13 @@ jobs: fail-on-cache-miss: true key: artifacts-system-${{ github.sha }} path: | + system-contracts/zkout + system-contracts/cache-forge + system-contracts/bootloader/build system-contracts/artifacts-zk system-contracts/cache-zk system-contracts/typechain system-contracts/contracts-preprocessed - system-contracts/bootloader/build - name: Run bootloader tests run: | @@ -111,11 +129,13 @@ jobs: fail-on-cache-miss: true key: artifacts-system-${{ github.sha }} path: | + system-contracts/zkout + system-contracts/cache-forge + system-contracts/bootloader/build system-contracts/artifacts-zk system-contracts/cache-zk system-contracts/typechain system-contracts/contracts-preprocessed - system-contracts/bootloader/build - name: Run tests run: yarn sc test @@ -123,35 +143,3 @@ jobs: - name: Print output logs of era_test_node if: always() run: cat era_test_node.log - - check-hashes: - needs: [build] - runs-on: ubuntu-latest - - steps: - - name: Checkout the repository - uses: actions/checkout@v4 - - - name: Use Node.js - uses: actions/setup-node@v3 - with: - node-version: 18.18.0 - cache: yarn - - - name: Install dependencies - run: yarn - - - name: Restore artifacts cache - uses: actions/cache/restore@v3 - with: - fail-on-cache-miss: true - key: artifacts-system-${{ github.sha }} - path: | - system-contracts/artifacts-zk - system-contracts/cache-zk - system-contracts/typechain - system-contracts/contracts-preprocessed - system-contracts/bootloader/build - - - name: Check hashes - run: yarn sc calculate-hashes:check diff --git a/.solhintignore b/.solhintignore index 2371ed166..785a7e178 100644 --- a/.solhintignore +++ b/.solhintignore @@ -17,6 +17,7 @@ l1-contracts-foundry/lib # l2-contracts l2-contracts/cache-zk l2-contracts/node_modules +l2-contracts/contracts/dev-contracts # system-contracts system-contracts/contracts/openzeppelin diff --git a/l1-contracts/contracts/bridge/L1SharedBridge.sol b/l1-contracts/contracts/bridge/L1SharedBridge.sol index eaddcccc7..1f81887bb 100644 --- a/l1-contracts/contracts/bridge/L1SharedBridge.sol +++ b/l1-contracts/contracts/bridge/L1SharedBridge.sol @@ -22,7 +22,7 @@ import {ETH_TOKEN_ADDRESS, TWO_BRIDGES_MAGIC_VALUE} from "../common/Config.sol"; import {IBridgehub, L2TransactionRequestTwoBridgesInner, L2TransactionRequestDirect} from "../bridgehub/IBridgehub.sol"; import {IGetters} from "../state-transition/chain-interfaces/IGetters.sol"; import {L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR} from "../common/L2ContractAddresses.sol"; -import {Unauthorized, ZeroAddress, SharedBridgeValueAlreadySet, SharedBridgeKey, NoFundsTransferred, ZeroBalance, ValueMismatch, TokensWithFeesNotSupported, NonEmptyMsgValue, L2BridgeNotSet, TokenNotSupported, DepositIncorrectAmount, EmptyDeposit, DepositExists, AddressAlreadyUsed, InvalidProof, DepositDoesNotExist, InsufficientChainBalance, SharedBridgeValueNotSet, WithdrawalAlreadyFinalized, WithdrawFailed, L2WithdrawalMessageWrongLength, InvalidSelector, SharedBridgeBalanceMismatch, SharedBridgeValueNotSet} from "../common/L1ContractErrors.sol"; +import {Unauthorized, ZeroAddress, SharedBridgeValueAlreadySet, SharedBridgeKey, NoFundsTransferred, ZeroBalance, ValueMismatch, TokensWithFeesNotSupported, NonEmptyMsgValue, L2BridgeNotSet, TokenNotSupported, DepositIncorrectAmount, EmptyDeposit, DepositExists, AddressAlreadyUsed, InvalidProof, DepositDoesNotExist, InsufficientChainBalance, SharedBridgeValueNotSet, WithdrawalAlreadyFinalized, WithdrawFailed, L2WithdrawalMessageWrongLength, InvalidSelector, SharedBridgeBalanceMismatch, SharedBridgeValueNotSet, NotPendingAdmin, L2BridgeAlreadySet} from "../common/L1ContractErrors.sol"; /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev @@ -130,7 +130,9 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Ownable2StepUpgrade /// @notice Checks that the message sender is either the owner or admin. modifier onlyOwnerOrAdmin() { - require(msg.sender == owner() || msg.sender == admin, "ShB not owner or admin"); + if (msg.sender != owner() && msg.sender != admin) { + revert Unauthorized(msg.sender); + } _; } @@ -174,7 +176,9 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Ownable2StepUpgrade /// @notice Accepts transfer of admin rights. Only pending admin can accept the role. function acceptAdmin() external { address currentPendingAdmin = pendingAdmin; - require(msg.sender == currentPendingAdmin, "ShB not pending admin"); // Only proposed by current admin address can claim the admin rights + if (msg.sender != currentPendingAdmin) { + revert NotPendingAdmin(); + } address previousAdmin = admin; admin = currentPendingAdmin; @@ -276,8 +280,12 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Ownable2StepUpgrade /// @param _chainId The chain ID for which the l2Bridge address is being initialized. /// @param _l2BridgeAddress The address of the L2 bridge contract. function initializeChainGovernance(uint256 _chainId, address _l2BridgeAddress) external onlyOwnerOrAdmin { - require(l2BridgeAddress[_chainId] == address(0), "ShB: l2 bridge already set"); - require(_l2BridgeAddress != address(0), "ShB: l2 bridge 0"); + if (l2BridgeAddress[_chainId] != address(0)) { + revert L2BridgeAlreadySet(_chainId); + } + if (_l2BridgeAddress == address(0)) { + revert ZeroAddress(); + } l2BridgeAddress[_chainId] = _l2BridgeAddress; } @@ -287,7 +295,9 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Ownable2StepUpgrade /// @param _chainId The chain ID for which the l2Bridge address is being initialized. /// @param _l2BridgeAddress The address of the L2 bridge contract. function reinitializeChainGovernance(uint256 _chainId, address _l2BridgeAddress) external onlyOwner { - require(l2BridgeAddress[_chainId] != address(0), "ShB: l2 bridge not yet set"); + if (l2BridgeAddress[_chainId] == address(0)) { + revert L2BridgeNotSet(_chainId); + } l2BridgeAddress[_chainId] = _l2BridgeAddress; } diff --git a/l1-contracts/contracts/common/L1ContractErrors.sol b/l1-contracts/contracts/common/L1ContractErrors.sol index bec5a56cd..62ff78917 100644 --- a/l1-contracts/contracts/common/L1ContractErrors.sol +++ b/l1-contracts/contracts/common/L1ContractErrors.sol @@ -137,6 +137,8 @@ error InvalidValue(); error L2BridgeNotDeployed(uint256 chainId); // 0xff8811ff error L2BridgeNotSet(uint256 chainId); +// 0x685577fa +error L2BridgeAlreadySet(uint256 chainId); // 0xcb5e4247 error L2BytecodeHashMismatch(bytes32 expected, bytes32 provided); // 0xfb5c22e6 @@ -193,6 +195,8 @@ error NonZeroAddress(address); error NotEnoughGas(); // 0xdd7e3621 error NotInitializedReentrancyGuard(); +// 0x058d9a1b +error NotPendingAdmin(); // 0xf3ed9dfa error OnlyEraSupported(); // 0x1a21feed diff --git a/l1-contracts/contracts/governance/AccessControlRestriction.sol b/l1-contracts/contracts/governance/AccessControlRestriction.sol deleted file mode 100644 index 3fc67f875..000000000 --- a/l1-contracts/contracts/governance/AccessControlRestriction.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -import {AccessToFallbackDenied, AccessToFunctionDenied} from "../common/L1ContractErrors.sol"; -import {IAccessControlRestriction} from "./IAccessControlRestriction.sol"; -import {AccessControlDefaultAdminRules} from "@openzeppelin/contracts-v4/access/AccessControlDefaultAdminRules.sol"; -import {IRestriction} from "./IRestriction.sol"; -import {Call} from "./Common.sol"; - -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -/// @notice The Restriction that is designed to provide the access control logic for the `ChainAdmin` contract. -/// @dev It inherits from `AccessControlDefaultAdminRules` without overriding `_setRoleAdmin` functionaity. In other -/// words, the `DEFAULT_ADMIN_ROLE` is the only role that can manage roles. This is done for simplicity. -/// @dev An instance of this restriction should be deployed separately for each `ChainAdmin` contract. -/// @dev IMPORTANT: this function does not validate the ability of the invoker to use `msg.value`. Thus, -/// either all callers with access to functions should be trusted to not steal ETH from the `ChainAdmin` account -/// or not ETH should be passively stored in `ChainAdmin` account. -contract AccessControlRestriction is IRestriction, IAccessControlRestriction, AccessControlDefaultAdminRules { - /// @notice Required roles to call a specific functions. - /// @dev Note, that the role 0 means the `DEFAULT_ADMIN_ROLE` from the `AccessControlDefaultAdminRules` contract. - mapping(address target => mapping(bytes4 selector => bytes32 requiredRole)) public requiredRoles; - - /// @notice Required roles to call a fallback function. - mapping(address target => bytes32 requiredRole) public requiredRolesForFallback; - - constructor( - uint48 initialDelay, - address initialDefaultAdmin - ) AccessControlDefaultAdminRules(initialDelay, initialDefaultAdmin) {} - - /// @notice Sets the required role for a specific function call. - /// @param _target The address of the contract. - /// @param _selector The selector of the function. - /// @param _requiredRole The required role. - function setRequiredRoleForCall( - address _target, - bytes4 _selector, - bytes32 _requiredRole - ) external onlyRole(DEFAULT_ADMIN_ROLE) { - requiredRoles[_target][_selector] = _requiredRole; - - emit RoleSet(_target, _selector, _requiredRole); - } - - /// @notice Sets the required role for a fallback function call. - /// @param _target The address of the contract. - /// @param _requiredRole The required role. - function setRequiredRoleForFallback(address _target, bytes32 _requiredRole) external onlyRole(DEFAULT_ADMIN_ROLE) { - requiredRolesForFallback[_target] = _requiredRole; - - emit FallbackRoleSet(_target, _requiredRole); - } - - /// @inheritdoc IRestriction - function validateCall(Call calldata _call, address _invoker) external view { - // Note, that since `DEFAULT_ADMIN_ROLE` is 0 and the default storage value for the - // `requiredRoles` and `requiredRolesForFallback` is 0, the default admin is by default a required - // role for all the functions. - if (_call.data.length < 4) { - if (!hasRole(requiredRolesForFallback[_call.target], _invoker)) { - revert AccessToFallbackDenied(_call.target, _invoker); - } - } else { - bytes4 selector = bytes4(_call.data[:4]); - if (!hasRole(requiredRoles[_call.target][selector], _invoker)) { - revert AccessToFunctionDenied(_call.target, selector, _invoker); - } - } - } -} diff --git a/l1-contracts/contracts/governance/ChainAdmin.sol b/l1-contracts/contracts/governance/ChainAdmin.sol index f6a93146f..4d9ff858f 100644 --- a/l1-contracts/contracts/governance/ChainAdmin.sol +++ b/l1-contracts/contracts/governance/ChainAdmin.sol @@ -2,76 +2,48 @@ pragma solidity 0.8.24; -// solhint-disable gas-length-in-loops - -import {NoCallsProvided, OnlySelfAllowed, RestrictionWasNotPresent, RestrictionWasAlreadyPresent} from "../common/L1ContractErrors.sol"; +import {Ownable2Step} from "@openzeppelin/contracts-v4/access/Ownable2Step.sol"; import {IChainAdmin} from "./IChainAdmin.sol"; -import {IRestriction} from "./IRestriction.sol"; -import {Call} from "./Common.sol"; - -import {EnumerableSet} from "@openzeppelin/contracts-v4/utils/structs/EnumerableSet.sol"; -import {ReentrancyGuard} from "../common/ReentrancyGuard.sol"; +import {IAdmin} from "../state-transition/chain-interfaces/IAdmin.sol"; +import {NoCallsProvided, Unauthorized, ZeroAddress} from "../common/L1ContractErrors.sol"; /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev /// @notice The contract is designed to hold the `admin` role in ZKSync Chain (State Transition) contracts. /// The owner of the contract can perform any external calls and also save the information needed for -/// the blockchain node to accept the protocol upgrade. -contract ChainAdmin is IChainAdmin, ReentrancyGuard { - using EnumerableSet for EnumerableSet.AddressSet; - - /// @notice Ensures that only the `ChainAdmin` contract itself can call the function. - /// @dev All functions that require access-control should use `onlySelf` modifier, while the access control logic - /// should be implemented in the restriction contracts. - modifier onlySelf() { - if (msg.sender != address(this)) { - revert OnlySelfAllowed(); - } - _; - } - - constructor(address[] memory _initialRestrictions) reentrancyGuardInitializer { - unchecked { - for (uint256 i = 0; i < _initialRestrictions.length; ++i) { - _addRestriction(_initialRestrictions[i]); - } - } - } - +/// the blockchain node to accept the protocol upgrade. Another role - `tokenMultiplierSetter` can be used in the contract +/// to change the base token gas price in the Chain contract. +contract ChainAdmin is IChainAdmin, Ownable2Step { /// @notice Mapping of protocol versions to their expected upgrade timestamps. /// @dev Needed for the offchain node administration to know when to start building batches with the new protocol version. mapping(uint256 protocolVersion => uint256 upgradeTimestamp) public protocolVersionToUpgradeTimestamp; - /// @notice The set of active restrictions. - EnumerableSet.AddressSet internal activeRestrictions; - - /// @notice Returns the list of active restrictions. - function getRestrictions() public view returns (address[] memory) { - return activeRestrictions.values(); - } - - /// @inheritdoc IChainAdmin - function isRestrictionActive(address _restriction) external view returns (bool) { - return activeRestrictions.contains(_restriction); - } + /// @notice The address which can call `setTokenMultiplier` function to change the base token gas price in the Chain contract. + /// @dev The token base price can be changed quite often, so the private key for this role is supposed to be stored in the node + /// and used by the automated service in a way similar to the sequencer workflow. + address public tokenMultiplierSetter; - /// @inheritdoc IChainAdmin - function addRestriction(address _restriction) external onlySelf { - _addRestriction(_restriction); + constructor(address _initialOwner, address _initialTokenMultiplierSetter) { + if (_initialOwner == address(0)) { + revert ZeroAddress(); + } + _transferOwnership(_initialOwner); + // Can be zero if no one has this permission. + tokenMultiplierSetter = _initialTokenMultiplierSetter; + emit NewTokenMultiplierSetter(address(0), _initialTokenMultiplierSetter); } - /// @inheritdoc IChainAdmin - function removeRestriction(address _restriction) external onlySelf { - if (!activeRestrictions.remove(_restriction)) { - revert RestrictionWasNotPresent(_restriction); - } - emit RestrictionRemoved(_restriction); + /// @notice Updates the address responsible for setting token multipliers on the Chain contract . + /// @param _tokenMultiplierSetter The new address to be set as the token multiplier setter. + function setTokenMultiplierSetter(address _tokenMultiplierSetter) external onlyOwner { + emit NewTokenMultiplierSetter(tokenMultiplierSetter, _tokenMultiplierSetter); + tokenMultiplierSetter = _tokenMultiplierSetter; } /// @notice Set the expected upgrade timestamp for a specific protocol version. /// @param _protocolVersion The ZKsync chain protocol version. /// @param _upgradeTimestamp The timestamp at which the chain node should expect the upgrade to happen. - function setUpgradeTimestamp(uint256 _protocolVersion, uint256 _upgradeTimestamp) external onlySelf { + function setUpgradeTimestamp(uint256 _protocolVersion, uint256 _upgradeTimestamp) external onlyOwner { protocolVersionToUpgradeTimestamp[_protocolVersion] = _upgradeTimestamp; emit UpdateUpgradeTimestamp(_protocolVersion, _upgradeTimestamp); } @@ -80,16 +52,12 @@ contract ChainAdmin is IChainAdmin, ReentrancyGuard { /// @param _calls Array of Call structures defining target, value, and data for each call. /// @param _requireSuccess If true, reverts transaction on any call failure. /// @dev Intended for batch processing of contract interactions, managing gas efficiency and atomicity of operations. - /// @dev Note, that this function lacks access control. It is expected that the access control is implemented in a separate restriction contract. - /// @dev Even though all the validation from external modules is executed via `staticcall`, the function - /// is marked as `nonReentrant` to prevent reentrancy attacks in case the staticcall restriction is lifted in the future. - function multicall(Call[] calldata _calls, bool _requireSuccess) external payable nonReentrant { + function multicall(Call[] calldata _calls, bool _requireSuccess) external payable onlyOwner { if (_calls.length == 0) { revert NoCallsProvided(); } + // solhint-disable-next-line gas-length-in-loops for (uint256 i = 0; i < _calls.length; ++i) { - _validateCall(_calls[i]); - // slither-disable-next-line arbitrary-send-eth (bool success, bytes memory returnData) = _calls[i].target.call{value: _calls[i].value}(_calls[i].data); if (_requireSuccess && !success) { @@ -102,27 +70,17 @@ contract ChainAdmin is IChainAdmin, ReentrancyGuard { } } - /// @dev Contract might receive/hold ETH as part of the maintenance process. - receive() external payable {} - - /// @notice Function that returns the current admin can perform the call. - /// @dev By default it always returns true, but can be overridden in derived contracts. - function _validateCall(Call calldata _call) internal view { - address[] memory restrictions = getRestrictions(); - - unchecked { - for (uint256 i = 0; i < restrictions.length; ++i) { - IRestriction(restrictions[i]).validateCall(_call, msg.sender); - } + /// @notice Sets the token multiplier in the specified Chain contract. + /// @param _chainContract The chain contract address where the token multiplier will be set. + /// @param _nominator The numerator part of the token multiplier. + /// @param _denominator The denominator part of the token multiplier. + function setTokenMultiplier(IAdmin _chainContract, uint128 _nominator, uint128 _denominator) external { + if (msg.sender != tokenMultiplierSetter) { + revert Unauthorized(msg.sender); } + _chainContract.setTokenMultiplier(_nominator, _denominator); } - /// @notice Adds a new restriction to the active restrictions set. - /// @param _restriction The address of the restriction contract to be added. - function _addRestriction(address _restriction) internal { - if (!activeRestrictions.add(_restriction)) { - revert RestrictionWasAlreadyPresent(_restriction); - } - emit RestrictionAdded(_restriction); - } + /// @dev Contract might receive/hold ETH as part of the maintenance process. + receive() external payable {} } diff --git a/l1-contracts/contracts/governance/IAccessControlRestriction.sol b/l1-contracts/contracts/governance/IAccessControlRestriction.sol deleted file mode 100644 index 3c9cfb5c5..000000000 --- a/l1-contracts/contracts/governance/IAccessControlRestriction.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -/// @title AccessControlRestriction contract interface -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -interface IAccessControlRestriction { - /// @notice Emitted when the required role for a specific function is set. - event RoleSet(address indexed target, bytes4 indexed selector, bytes32 requiredRole); - - /// @notice Emitted when the required role for a fallback function is set. - event FallbackRoleSet(address indexed target, bytes32 requiredRole); -} diff --git a/l1-contracts/contracts/governance/IChainAdmin.sol b/l1-contracts/contracts/governance/IChainAdmin.sol index 1ef3144c2..d5d8f117c 100644 --- a/l1-contracts/contracts/governance/IChainAdmin.sol +++ b/l1-contracts/contracts/governance/IChainAdmin.sol @@ -2,37 +2,36 @@ pragma solidity 0.8.24; -import {Call} from "./Common.sol"; +import {IAdmin} from "../state-transition/chain-interfaces/IAdmin.sol"; /// @title ChainAdmin contract interface /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev interface IChainAdmin { + /// @dev Represents a call to be made during multicall. + /// @param target The address to which the call will be made. + /// @param value The amount of Ether (in wei) to be sent along with the call. + /// @param data The calldata to be executed on the `target` address. + struct Call { + address target; + uint256 value; + bytes data; + } + /// @notice Emitted when the expected upgrade timestamp for a specific protocol version is set. - event UpdateUpgradeTimestamp(uint256 indexed protocolVersion, uint256 upgradeTimestamp); + event UpdateUpgradeTimestamp(uint256 indexed _protocolVersion, uint256 _upgradeTimestamp); /// @notice Emitted when the call is executed from the contract. - event CallExecuted(Call call, bool success, bytes returnData); - - /// @notice Emitted when a new restriction is added. - event RestrictionAdded(address indexed restriction); + event CallExecuted(Call _call, bool _success, bytes _returnData); - /// @notice Emitted when a restriction is removed. - event RestrictionRemoved(address indexed restriction); + /// @notice Emitted when the new token multiplier address is set. + event NewTokenMultiplierSetter(address _oldTokenMultiplierSetter, address _newTokenMultiplierSetter); - /// @notice Returns the list of active restrictions. - function getRestrictions() external view returns (address[] memory); + function setTokenMultiplierSetter(address _tokenMultiplierSetter) external; - /// @notice Checks if the restriction is active. - /// @param _restriction The address of the restriction contract. - function isRestrictionActive(address _restriction) external view returns (bool); + function setUpgradeTimestamp(uint256 _protocolVersion, uint256 _upgradeTimestamp) external; - /// @notice Adds a new restriction to the active restrictions set. - /// @param _restriction The address of the restriction contract. - function addRestriction(address _restriction) external; + function multicall(Call[] calldata _calls, bool _requireSuccess) external payable; - /// @notice Removes a restriction from the active restrictions set. - /// @param _restriction The address of the restriction contract. - /// @dev Sometimes restrictions might need to enforce their permanence (e.g. if a chain should be a rollup forever). - function removeRestriction(address _restriction) external; + function setTokenMultiplier(IAdmin _chainContract, uint128 _nominator, uint128 _denominator) external; } diff --git a/l1-contracts/contracts/governance/IPermanentRestriction.sol b/l1-contracts/contracts/governance/IPermanentRestriction.sol deleted file mode 100644 index 548866b9f..000000000 --- a/l1-contracts/contracts/governance/IPermanentRestriction.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -/// @notice The interface for the permanent restriction contract. -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -interface IPermanentRestriction { - /// @notice Emitted when the implementation is allowed or disallowed. - event AdminImplementationAllowed(bytes32 indexed implementationHash, bool isAllowed); - - /// @notice Emitted when a certain calldata is allowed or disallowed. - event AllowedDataChanged(bytes data, bool isAllowed); - - /// @notice Emitted when the selector is labeled as validated or not. - event SelectorValidationChanged(bytes4 indexed selector, bool isValidated); -} diff --git a/l1-contracts/contracts/governance/IRestriction.sol b/l1-contracts/contracts/governance/IRestriction.sol deleted file mode 100644 index b2cc79428..000000000 --- a/l1-contracts/contracts/governance/IRestriction.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -import {Call} from "./Common.sol"; - -/// @title Restriction contract interface -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -interface IRestriction { - /// @notice Ensures that the invoker has the required role to call the function. - /// @param _call The call data. - /// @param _invoker The address of the invoker. - function validateCall(Call calldata _call, address _invoker) external view; -} diff --git a/l1-contracts/contracts/governance/PermanentRestriction.sol b/l1-contracts/contracts/governance/PermanentRestriction.sol deleted file mode 100644 index acf75a67f..000000000 --- a/l1-contracts/contracts/governance/PermanentRestriction.sol +++ /dev/null @@ -1,186 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -import {CallNotAllowed, ChainZeroAddress, NotAHyperchain, NotAnAdmin, RemovingPermanentRestriction, ZeroAddress, UnallowedImplementation} from "../common/L1ContractErrors.sol"; - -import {Ownable2Step} from "@openzeppelin/contracts-v4/access/Ownable2Step.sol"; - -import {Call} from "./Common.sol"; -import {IRestriction} from "./IRestriction.sol"; -import {IChainAdmin} from "./IChainAdmin.sol"; -import {IBridgehub} from "../bridgehub/IBridgehub.sol"; -import {IZkSyncHyperchain} from "../state-transition/chain-interfaces/IZkSyncHyperchain.sol"; -import {IAdmin} from "../state-transition/chain-interfaces/IAdmin.sol"; - -import {IPermanentRestriction} from "./IPermanentRestriction.sol"; - -/// @title PermanentRestriction contract -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -/// @notice This contract should be used by chains that wish to guarantee that certain security -/// properties are preserved forever. -/// @dev To be deployed as a transparent upgradable proxy, owned by a trusted decentralized governance. -/// @dev Once of the instances of such contract is to ensure that a ZkSyncHyperchain is a rollup forever. -contract PermanentRestriction is IRestriction, IPermanentRestriction, Ownable2Step { - /// @notice The address of the Bridgehub contract. - IBridgehub public immutable BRIDGE_HUB; - - /// @notice The mapping of the allowed admin implementations. - mapping(bytes32 implementationCodeHash => bool isAllowed) public allowedAdminImplementations; - - /// @notice The mapping of the allowed calls. - mapping(bytes allowedCalldata => bool isAllowed) public allowedCalls; - - /// @notice The mapping of the validated selectors. - mapping(bytes4 selector => bool isValidated) public validatedSelectors; - - constructor(address _initialOwner, IBridgehub _bridgehub) { - BRIDGE_HUB = _bridgehub; - - // solhint-disable-next-line gas-custom-errors, reason-string - if (_initialOwner == address(0)) { - revert ZeroAddress(); - } - _transferOwnership(_initialOwner); - } - - /// @notice Allows a certain `ChainAdmin` implementation to be used as an admin. - /// @param _implementationHash The hash of the implementation code. - /// @param _isAllowed The flag that indicates if the implementation is allowed. - function allowAdminImplementation(bytes32 _implementationHash, bool _isAllowed) external onlyOwner { - allowedAdminImplementations[_implementationHash] = _isAllowed; - - emit AdminImplementationAllowed(_implementationHash, _isAllowed); - } - - /// @notice Allows a certain calldata for a selector to be used. - /// @param _data The calldata for the function. - /// @param _isAllowed The flag that indicates if the calldata is allowed. - function setAllowedData(bytes calldata _data, bool _isAllowed) external onlyOwner { - allowedCalls[_data] = _isAllowed; - - emit AllowedDataChanged(_data, _isAllowed); - } - - /// @notice Allows a certain selector to be validated. - /// @param _selector The selector of the function. - /// @param _isValidated The flag that indicates if the selector is validated. - function setSelectorIsValidated(bytes4 _selector, bool _isValidated) external onlyOwner { - validatedSelectors[_selector] = _isValidated; - - emit SelectorValidationChanged(_selector, _isValidated); - } - - /// @inheritdoc IRestriction - function validateCall( - Call calldata _call, - address // _invoker - ) external view override { - _validateAsChainAdmin(_call); - _validateRemoveRestriction(_call); - } - - /// @notice Validates the call as the chain admin - /// @param _call The call data. - function _validateAsChainAdmin(Call calldata _call) internal view { - if (!_isAdminOfAChain(_call.target)) { - // We only validate calls related to being an admin of a chain - return; - } - - // All calls with the length of the data below 4 will get into `receive`/`fallback` functions, - // we consider it to always be allowed. - if (_call.data.length < 4) { - return; - } - - bytes4 selector = bytes4(_call.data[:4]); - - if (selector == IAdmin.setPendingAdmin.selector) { - _validateNewAdmin(_call); - return; - } - - if (!validatedSelectors[selector]) { - // The selector is not validated, any data is allowed. - return; - } - - if (!allowedCalls[_call.data]) { - revert CallNotAllowed(_call.data); - } - } - - /// @notice Validates the correctness of the new admin. - /// @param _call The call data. - /// @dev Ensures that the admin has a whitelisted implementation and does not remove this restriction. - function _validateNewAdmin(Call calldata _call) internal view { - address newChainAdmin = abi.decode(_call.data[4:], (address)); - - bytes32 implementationCodeHash = newChainAdmin.codehash; - - if (!allowedAdminImplementations[implementationCodeHash]) { - revert UnallowedImplementation(implementationCodeHash); - } - - // Since the implementation is known to be correct (from the checks above), we - // can safely trust the returned value from the call below - if (!IChainAdmin(newChainAdmin).isRestrictionActive(address(this))) { - revert RemovingPermanentRestriction(); - } - } - - /// @notice Validates the removal of the restriction. - /// @param _call The call data. - /// @dev Ensures that this restriction is not removed. - function _validateRemoveRestriction(Call calldata _call) internal view { - if (_call.target != msg.sender) { - return; - } - - if (bytes4(_call.data[:4]) != IChainAdmin.removeRestriction.selector) { - return; - } - - address removedRestriction = abi.decode(_call.data[4:], (address)); - - if (removedRestriction == address(this)) { - revert RemovingPermanentRestriction(); - } - } - - /// @notice Checks if the `msg.sender` is an admin of a certain ZkSyncHyperchain. - /// @param _chain The address of the chain. - function _isAdminOfAChain(address _chain) internal view returns (bool) { - (bool success, ) = address(this).staticcall(abi.encodeCall(this.tryCompareAdminOfAChain, (_chain, msg.sender))); - return success; - } - - /// @notice Tries to compare the admin of a chain with the potential admin. - /// @param _chain The address of the chain. - /// @param _potentialAdmin The address of the potential admin. - /// @dev This function reverts if the `_chain` is not a ZkSyncHyperchain or the `_potentialAdmin` is not the - /// admin of the chain. - function tryCompareAdminOfAChain(address _chain, address _potentialAdmin) external view { - if (_chain == address(0)) { - revert ChainZeroAddress(); - } - - // Unfortunately there is no easy way to double check that indeed the `_chain` is a ZkSyncHyperchain. - // So we do the following: - // - Query it for `chainId`. If it reverts, it is not a ZkSyncHyperchain. - // - Query the Bridgehub for the Hyperchain with the given `chainId`. - // - We compare the corresponding addresses - uint256 chainId = IZkSyncHyperchain(_chain).getChainId(); - if (BRIDGE_HUB.getHyperchain(chainId) != _chain) { - revert NotAHyperchain(_chain); - } - - // Now, the chain is known to be a hyperchain, so it should implement the corresponding interface - address admin = IZkSyncHyperchain(_chain).getAdmin(); - if (admin != _potentialAdmin) { - revert NotAnAdmin(admin, _potentialAdmin); - } - } -} diff --git a/l1-contracts/deploy-scripts/ChainConfigurationReader.s.sol b/l1-contracts/deploy-scripts/ChainConfigurationReader.s.sol new file mode 100644 index 000000000..54a9ebe8a --- /dev/null +++ b/l1-contracts/deploy-scripts/ChainConfigurationReader.s.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.21; + +import {Script, console2 as console} from "forge-std/Script.sol"; +import {Vm} from "forge-std/Vm.sol"; +import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol"; +import {PubdataPricingMode} from "contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol"; +import {StateTransitionManager} from "contracts/state-transition/StateTransitionManager.sol"; +import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol"; +import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; + +contract ChainConfigurationReader is Script { + function run(address stmAddress, uint256 chainId) public { + StateTransitionManager stm = StateTransitionManager(stmAddress); + IZkSyncHyperchain diamondProxy = IZkSyncHyperchain(stm.getHyperchain(chainId)); + address payable chainAdmin = payable(stm.getChainAdmin(chainId)); + address tokenMultiplierSetter = ChainAdmin(chainAdmin).tokenMultiplierSetter(); + address owner = ChainAdmin(chainAdmin).owner(); + address basetoken = diamondProxy.getBaseToken(); + (uint32 major, uint32 minor, uint32 patch) = diamondProxy.getSemverProtocolVersion(); + address validatorTimelock = stm.validatorTimelock(); + PubdataPricingMode pubdataPricingMode = diamondProxy.getPubdataPricingMode(); + + uint256 baseTokenGasPriceMultiplierNominator = diamondProxy.baseTokenGasPriceMultiplierNominator(); + uint256 baseTokenGasPriceMultiplierDenominator = diamondProxy.baseTokenGasPriceMultiplierDenominator(); + + console.log("=====INFO ABOUT CHAIN %d =====", chainId); + console.log("Diamond Proxy %s", address(diamondProxy)); + console.log("ChainAdmin %s", chainAdmin); + console.log("Token Multiplier Setter of ChainAdmin %s", tokenMultiplierSetter); + console.log("Owner of ChainAdmin %s", owner); + console.log("Protocol Version %d.%d.%d", major, minor, patch); + if (pubdataPricingMode == PubdataPricingMode.Validium) { + console.log("Pubdata Pricing Mode: Validium"); + } else if (pubdataPricingMode == PubdataPricingMode.Rollup) { + console.log("Pubdata Pricing Mode: Rollup"); + } + + console.log("==Validators=="); + getNewValidators(validatorTimelock, chainId); + console.log("==BASE TOKEN=="); + console.log("address: %s", basetoken); + console.log("nominator: %s", baseTokenGasPriceMultiplierNominator); + console.log("denominator: %s", baseTokenGasPriceMultiplierDenominator); + } + + function getNewValidators(address validatorTimelock, uint256 chainId) internal { + bytes32[] memory topics = new bytes32[](2); + topics[0] = ValidatorTimelock.ValidatorAdded.selector; + topics[1] = bytes32(chainId); + Vm.EthGetLogs[] memory logs = vm.eth_getLogs(1, block.number, validatorTimelock, topics); + for (uint256 i = 0; i < logs.length; i++) { + Vm.EthGetLogs memory log = logs[i]; + console.log("New Validator", bytesToAddress(log.data)); + } + } + + function bytesToAddress(bytes memory bys) private pure returns (address addr) { + assembly { + addr := mload(add(bys, 32)) + } + } +} diff --git a/l1-contracts/deploy-scripts/DeployErc20.s.sol b/l1-contracts/deploy-scripts/DeployErc20.s.sol index 60f34230a..9a7c9cfa9 100644 --- a/l1-contracts/deploy-scripts/DeployErc20.s.sol +++ b/l1-contracts/deploy-scripts/DeployErc20.s.sol @@ -83,7 +83,7 @@ contract DeployErc20Script is Script { function deployTokens() internal { uint256 tokensLength = config.tokens.length; for (uint256 i = 0; i < tokensLength; ++i) { - TokenDescription memory token = config.tokens[i]; + TokenDescription storage token = config.tokens[i]; console.log("Deploying token:", token.name); address tokenAddress = deployErc20({ name: token.name, diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index cef851957..9735de2b1 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -600,12 +600,15 @@ contract DeployL1Script is Script { Bridgehub bridgehub = Bridgehub(addresses.bridgehub.bridgehubProxy); bridgehub.transferOwnership(addresses.governance); + bridgehub.setPendingAdmin(addresses.chainAdmin); L1SharedBridge sharedBridge = L1SharedBridge(addresses.bridges.sharedBridgeProxy); sharedBridge.transferOwnership(addresses.governance); + sharedBridge.setPendingAdmin(addresses.chainAdmin); StateTransitionManager stm = StateTransitionManager(addresses.stateTransition.stateTransitionProxy); stm.transferOwnership(addresses.governance); + stm.setPendingAdmin(addresses.chainAdmin); vm.stopBroadcast(); console.log("Owners updated"); @@ -716,6 +719,7 @@ contract DeployL1Script is Script { addresses.blobVersionedHashRetriever ); vm.serializeAddress("deployed_addresses", "validator_timelock_addr", addresses.validatorTimelock); + vm.serializeAddress("deployed_addresses", "chain_admin", addresses.chainAdmin); vm.serializeString("deployed_addresses", "bridgehub", bridgehub); vm.serializeString("deployed_addresses", "state_transition", stateTransition); string memory deployedAddresses = vm.serializeString("deployed_addresses", "bridges", bridges); diff --git a/l1-contracts/deploy-scripts/DeployL2Contracts.sol b/l1-contracts/deploy-scripts/DeployL2Contracts.sol index fb3f35024..899cc9263 100644 --- a/l1-contracts/deploy-scripts/DeployL2Contracts.sol +++ b/l1-contracts/deploy-scripts/DeployL2Contracts.sol @@ -31,7 +31,9 @@ contract DeployL2Script is Script { address l2SharedBridgeProxy; address consensusRegistryImplementation; address consensusRegistryProxy; + address multicall3; address forceDeployUpgraderAddress; + address timestampAsserter; } struct ContractsBytecodes { @@ -42,7 +44,9 @@ contract DeployL2Script is Script { bytes l2SharedBridgeProxyBytecode; bytes consensusRegistryBytecode; bytes consensusRegistryProxyBytecode; + bytes multicall3Bytecode; bytes forceDeployUpgrader; + bytes timestampAsserterBytecode; } function run() public { @@ -64,6 +68,8 @@ contract DeployL2Script is Script { deployForceDeployer(); deployConsensusRegistry(); deployConsensusRegistryProxy(); + deployMulticall3(); + deployTimestampAsserter(); saveOutput(); } @@ -107,42 +113,66 @@ contract DeployL2Script is Script { saveOutput(); } + function runDeployMulticall3() public { + initializeConfig(); + loadContracts(false); + + deployMulticall3(); + + saveOutput(); + } + + function runDeployTimestampAsserter() public { + initializeConfig(); + loadContracts(false); + + deployTimestampAsserter(); + + saveOutput(); + } + function loadContracts(bool legacyBridge) internal { //HACK: Meanwhile we are not integrated foundry zksync we use contracts that has been built using hardhat - contracts.l2StandardErc20FactoryBytecode = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.json" + contracts.l2StandardErc20FactoryBytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/UpgradeableBeacon.sol/UpgradeableBeacon.json" ); - contracts.beaconProxy = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol/BeaconProxy.json" - ); - contracts.l2StandardErc20Bytecode = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/contracts/bridge/L2StandardERC20.sol/L2StandardERC20.json" + contracts.beaconProxy = Utils.readFoundryBytecode("/../l2-contracts/zkout/BeaconProxy.sol/BeaconProxy.json"); + contracts.l2StandardErc20Bytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/L2StandardERC20.sol/L2StandardERC20.json" ); if (legacyBridge) { - contracts.l2SharedBridgeBytecode = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/contracts/dev-contracts/DevL2SharedBridge.sol/DevL2SharedBridge.json" + contracts.l2SharedBridgeBytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/DevL2SharedBridge.sol/DevL2SharedBridge.json" ); } else { - contracts.l2SharedBridgeBytecode = Utils.readHardhatBytecode( + contracts.l2SharedBridgeBytecode = Utils.readFoundryBytecode( "/../l2-contracts/zkout/L2SharedBridge.sol/L2SharedBridge.json" ); } - contracts.l2SharedBridgeProxyBytecode = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json" + contracts.l2SharedBridgeProxyBytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json" ); - contracts.consensusRegistryBytecode = Utils.readHardhatBytecode( + contracts.consensusRegistryBytecode = Utils.readFoundryBytecode( "/../l2-contracts/zkout/ConsensusRegistry.sol/ConsensusRegistry.json" ); - contracts.consensusRegistryProxyBytecode = Utils.readHardhatBytecode( + contracts.consensusRegistryProxyBytecode = Utils.readFoundryBytecode( "/../l2-contracts/zkout/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json" ); - contracts.forceDeployUpgrader = Utils.readHardhatBytecode( + contracts.multicall3Bytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/Multicall3.sol/Multicall3.json" + ); + + contracts.forceDeployUpgrader = Utils.readFoundryBytecode( "/../l2-contracts/zkout/ForceDeployUpgrader.sol/ForceDeployUpgrader.json" ); + + contracts.timestampAsserterBytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/TimestampAsserter.sol/TimestampAsserter.json" + ); } function initializeConfig() internal { @@ -163,6 +193,8 @@ contract DeployL2Script is Script { vm.serializeAddress("root", "l2_shared_bridge_proxy", config.l2SharedBridgeProxy); vm.serializeAddress("root", "consensus_registry_implementation", config.consensusRegistryImplementation); vm.serializeAddress("root", "consensus_registry_proxy", config.consensusRegistryProxy); + vm.serializeAddress("root", "multicall3", config.multicall3); + vm.serializeAddress("root", "timestamp_asserter", config.timestampAsserter); string memory toml = vm.serializeAddress("root", "l2_default_upgrader", config.forceDeployUpgraderAddress); string memory root = vm.projectRoot(); string memory path = string.concat(root, "/script-out/output-deploy-l2-contracts.toml"); @@ -264,6 +296,35 @@ contract DeployL2Script is Script { }); } + function deployMulticall3() internal { + // Multicall3 doesn't have a constructor. + bytes memory constructorData = ""; + + config.multicall3 = Utils.deployThroughL1({ + bytecode: contracts.multicall3Bytecode, + constructorargs: constructorData, + create2salt: "", + l2GasLimit: Utils.MAX_PRIORITY_TX_GAS, + factoryDeps: new bytes[](0), + chainId: config.chainId, + bridgehubAddress: config.bridgehubAddress, + l1SharedBridgeProxy: config.l1SharedBridgeProxy + }); + } + + function deployTimestampAsserter() internal { + config.timestampAsserter = Utils.deployThroughL1({ + bytecode: contracts.timestampAsserterBytecode, + constructorargs: hex"", + create2salt: "", + l2GasLimit: Utils.MAX_PRIORITY_TX_GAS, + factoryDeps: new bytes[](0), + chainId: config.chainId, + bridgehubAddress: config.bridgehubAddress, + l1SharedBridgeProxy: config.l1SharedBridgeProxy + }); + } + // Deploy a transparent upgradable proxy for the already deployed consensus registry // implementation and save its address into the config. function deployConsensusRegistryProxy() internal { @@ -298,13 +359,11 @@ contract DeployL2Script is Script { function initializeChain() internal { L1SharedBridge bridge = L1SharedBridge(config.l1SharedBridgeProxy); - Utils.executeUpgrade({ - _governor: bridge.owner(), - _salt: bytes32(0), + Utils.chainAdminMulticall({ + _chainAdmin: bridge.admin(), _target: config.l1SharedBridgeProxy, _data: abi.encodeCall(bridge.initializeChainGovernance, (config.chainId, config.l2SharedBridgeProxy)), - _value: 0, - _delay: 0 + _value: 0 }); } } diff --git a/l1-contracts/deploy-scripts/EIP712Utils.sol b/l1-contracts/deploy-scripts/EIP712Utils.sol new file mode 100644 index 000000000..5f1aeb958 --- /dev/null +++ b/l1-contracts/deploy-scripts/EIP712Utils.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +library EIP712Utils { + bytes32 private constant TYPE_HASH = + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); + + function buildDomainHash( + address _verifyingContract, + string memory _name, + string memory _version + ) internal view returns (bytes32) { + return + keccak256( + // solhint-disable-next-line func-named-parameters + abi.encode( + TYPE_HASH, + keccak256(bytes(_name)), + keccak256(bytes(_version)), + block.chainid, + _verifyingContract + ) + ); + } + + function buildDigest(bytes32 _domainHash, bytes32 _message) internal view returns (bytes32) { + return keccak256(abi.encodePacked("\x19\x01", _domainHash, _message)); + } +} diff --git a/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol b/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol index 0a7e20a53..8e23cc7e3 100644 --- a/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol +++ b/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol @@ -13,6 +13,8 @@ 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 {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; +import {Call} from "contracts/governance/Common.sol"; import {Utils} from "./Utils.sol"; /** @@ -106,24 +108,24 @@ contract PrepareZKChainRegistrationCalldataScript is Script { checkBaseTokenAddress(); - IGovernance.Call[] memory calls; + Call[] memory calls; uint256 cnt = 0; if (!IBridgehub(ecosystem.bridgehub).tokenIsRegistered(config.baseToken)) { - calls = new IGovernance.Call[](2); + calls = new Call[](2); console.log("Adding a call to register base token on the bridgehub"); - IGovernance.Call memory baseTokenRegistrationCall = prepareRegisterBaseTokenCall(); + Call memory baseTokenRegistrationCall = prepareRegisterBaseTokenCall(); calls[cnt] = baseTokenRegistrationCall; ++cnt; } else { - calls = new IGovernance.Call[](1); + calls = new Call[](1); } - IGovernance.Call memory registerChainCall = prepareRegisterHyperchainCall(); + Call memory registerChainCall = prepareRegisterHyperchainCall(); calls[cnt] = registerChainCall; ++cnt; address l2SharedBridgeProxy = computeL2BridgeAddress(); - IGovernance.Call memory initChainCall = prepareInitializeChainGovernanceCall(l2SharedBridgeProxy); + Call memory initChainCall = prepareInitializeChainGovernanceCall(l2SharedBridgeProxy); scheduleTransparentCalldata(calls, initChainCall); } @@ -178,12 +180,12 @@ contract PrepareZKChainRegistrationCalldataScript is Script { console.log("Using base token address:", config.baseToken); } - function prepareRegisterBaseTokenCall() internal view returns (IGovernance.Call memory) { + function prepareRegisterBaseTokenCall() internal view returns (Call memory) { Bridgehub bridgehub = Bridgehub(ecosystem.bridgehub); bytes memory data = abi.encodeCall(bridgehub.addToken, (config.baseToken)); - return IGovernance.Call({target: ecosystem.bridgehub, value: 0, data: data}); + return Call({target: ecosystem.bridgehub, value: 0, data: data}); } // @dev Computes the address of the L2 bridge and the L2 bridge proxy @@ -267,7 +269,7 @@ contract PrepareZKChainRegistrationCalldataScript is Script { return proxyContractAddress; } - function prepareRegisterHyperchainCall() internal view returns (IGovernance.Call memory) { + function prepareRegisterHyperchainCall() internal view returns (Call memory) { Bridgehub bridgehub = Bridgehub(ecosystem.bridgehub); bytes memory data = abi.encodeCall( @@ -282,26 +284,21 @@ contract PrepareZKChainRegistrationCalldataScript is Script { ) ); - return IGovernance.Call({target: ecosystem.bridgehub, value: 0, data: data}); + return Call({target: ecosystem.bridgehub, value: 0, data: data}); } - function prepareInitializeChainGovernanceCall( - address l2SharedBridgeProxy - ) internal view returns (IGovernance.Call memory) { + function prepareInitializeChainGovernanceCall(address l2SharedBridgeProxy) internal view returns (Call memory) { L1SharedBridge bridge = L1SharedBridge(ecosystem.l1SharedBridgeProxy); bytes memory data = abi.encodeCall(bridge.initializeChainGovernance, (config.chainId, l2SharedBridgeProxy)); - return IGovernance.Call({target: ecosystem.l1SharedBridgeProxy, value: 0, data: data}); + return Call({target: ecosystem.l1SharedBridgeProxy, value: 0, data: data}); } // @dev Prepares a call to schedule a transparent operation on the governance contract // `calls` is an array of calls that will be executed in the first stage (add a token to BH, create a new chain) // `initChainGovCall` is a call that will be executed in the second stage (register the L2 bridge on the L1 shared bridge) - function scheduleTransparentCalldata( - IGovernance.Call[] memory calls, - IGovernance.Call memory initChainGovCall - ) internal { + function scheduleTransparentCalldata(Call[] memory calls, Call memory initChainGovCall) internal { IGovernance governance = IGovernance(ecosystem.governance); IGovernance.Operation memory operation = IGovernance.Operation({ @@ -313,7 +310,7 @@ contract PrepareZKChainRegistrationCalldataScript is Script { bytes memory scheduleCalldata = abi.encodeCall(governance.scheduleTransparent, (operation, 0)); bytes memory executeCalldata = abi.encodeCall(governance.execute, (operation)); - IGovernance.Call[] memory initChainGovArray = new IGovernance.Call[](1); + Call[] memory initChainGovArray = new Call[](1); initChainGovArray[0] = initChainGovCall; IGovernance.Operation memory operation2 = IGovernance.Operation({ diff --git a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol index 94acb2f02..6104a3013 100644 --- a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol +++ b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol @@ -7,13 +7,11 @@ import {Script, console2 as console} from "forge-std/Script.sol"; import {Vm} from "forge-std/Vm.sol"; import {stdToml} from "forge-std/StdToml.sol"; -import {Ownable} from "@openzeppelin/contracts-v4/access/Ownable.sol"; -import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; +import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol"; import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol"; import {Governance} from "contracts/governance/Governance.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; -import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; import {Utils} from "./Utils.sol"; import {PubdataPricingMode} from "contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol"; @@ -120,20 +118,17 @@ contract RegisterHyperchainScript is Script { } function registerTokenOnBridgehub() internal { - IBridgehub bridgehub = IBridgehub(config.bridgehub); - Ownable ownable = Ownable(config.bridgehub); + Bridgehub bridgehub = Bridgehub(config.bridgehub); if (bridgehub.tokenIsRegistered(config.baseToken)) { console.log("Token already registered on Bridgehub"); } else { bytes memory data = abi.encodeCall(bridgehub.addToken, (config.baseToken)); - Utils.executeUpgrade({ - _governor: ownable.owner(), - _salt: bytes32(config.bridgehubCreateNewChainSalt), + Utils.chainAdminMulticall({ + _chainAdmin: bridgehub.admin(), _target: config.bridgehub, _data: data, - _value: 0, - _delay: 0 + _value: 0 }); console.log("Token registered on Bridgehub"); } @@ -152,19 +147,12 @@ contract RegisterHyperchainScript is Script { function deployChainAdmin() internal { vm.broadcast(); - AccessControlRestriction restriction = new AccessControlRestriction(0, config.ownerAddress); - - address[] memory restrictions = new address[](1); - restrictions[0] = address(restriction); - - vm.broadcast(); - ChainAdmin chainAdmin = new ChainAdmin(restrictions); + ChainAdmin chainAdmin = new ChainAdmin(config.ownerAddress, address(0)); config.chainAdmin = address(chainAdmin); } function registerHyperchain() internal { - IBridgehub bridgehub = IBridgehub(config.bridgehub); - Ownable ownable = Ownable(config.bridgehub); + Bridgehub bridgehub = Bridgehub(config.bridgehub); vm.recordLogs(); bytes memory data = abi.encodeCall( @@ -179,14 +167,7 @@ contract RegisterHyperchainScript is Script { ) ); - Utils.executeUpgrade({ - _governor: ownable.owner(), - _salt: bytes32(config.bridgehubCreateNewChainSalt), - _target: config.bridgehub, - _data: data, - _value: 0, - _delay: 0 - }); + Utils.chainAdminMulticall({_chainAdmin: bridgehub.admin(), _target: config.bridgehub, _data: data, _value: 0}); console.log("Hyperchain registered"); // Get new diamond proxy address from emitted events diff --git a/l1-contracts/deploy-scripts/Utils.sol b/l1-contracts/deploy-scripts/Utils.sol index dc96b32b2..24bd49607 100644 --- a/l1-contracts/deploy-scripts/Utils.sol +++ b/l1-contracts/deploy-scripts/Utils.sol @@ -13,6 +13,27 @@ import {IERC20} from "@openzeppelin/contracts-v4/token/ERC20/IERC20.sol"; import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA} from "contracts/common/Config.sol"; import {L2_DEPLOYER_SYSTEM_CONTRACT_ADDR} from "contracts/common/L2ContractAddresses.sol"; import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; +import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; +import {EIP712Utils} from "./EIP712Utils.sol"; +import {IProtocolUpgradeHandler} from "./interfaces/IProtocolUpgradeHandler.sol"; +import {IEmergencyUpgrageBoard} from "./interfaces/IEmergencyUpgrageBoard.sol"; +import {IMultisig} from "./interfaces/IMultisig.sol"; +import {ISafe} from "./interfaces/ISafe.sol"; + +/// @dev EIP-712 TypeHash for the emergency protocol upgrade execution approved by the guardians. +bytes32 constant EXECUTE_EMERGENCY_UPGRADE_GUARDIANS_TYPEHASH = keccak256( + "ExecuteEmergencyUpgradeGuardians(bytes32 id)" +); + +/// @dev EIP-712 TypeHash for the emergency protocol upgrade execution approved by the Security Council. +bytes32 constant EXECUTE_EMERGENCY_UPGRADE_SECURITY_COUNCIL_TYPEHASH = keccak256( + "ExecuteEmergencyUpgradeSecurityCouncil(bytes32 id)" +); + +/// @dev EIP-712 TypeHash for the emergency protocol upgrade execution approved by the ZK Foundation. +bytes32 constant EXECUTE_EMERGENCY_UPGRADE_ZK_FOUNDATION_TYPEHASH = keccak256( + "ExecuteEmergencyUpgradeZKFoundation(bytes32 id)" +); library Utils { // Cheatcodes address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D. @@ -300,6 +321,15 @@ library Utils { return bytecode; } + function chainAdminMulticall(address _chainAdmin, address _target, bytes memory _data, uint256 _value) internal { + IChainAdmin chainAdmin = IChainAdmin(_chainAdmin); + + IChainAdmin.Call[] memory calls = new IChainAdmin.Call[](1); + calls[0] = IChainAdmin.Call({target: _target, value: _value, data: _data}); + vm.broadcast(); + chainAdmin.multicall(calls, true); + } + function executeUpgrade( address _governor, bytes32 _salt, @@ -326,4 +356,117 @@ library Utils { } vm.stopBroadcast(); } + + function executeEmergencyProtocolUpgrade( + IProtocolUpgradeHandler _protocolUpgradeHandler, + Vm.Wallet memory _governorWallet, + IProtocolUpgradeHandler.Call[] memory _calls, + bytes32 _salt + ) internal returns (bytes memory) { + bytes32 upgradeId; + bytes32 emergencyUpgradeBoardDigest; + { + address emergencyUpgradeBoard = _protocolUpgradeHandler.emergencyUpgradeBoard(); + IProtocolUpgradeHandler.UpgradeProposal memory upgradeProposal = IProtocolUpgradeHandler.UpgradeProposal({ + calls: _calls, + salt: _salt, + executor: emergencyUpgradeBoard + }); + upgradeId = keccak256(abi.encode(upgradeProposal)); + emergencyUpgradeBoardDigest = EIP712Utils.buildDomainHash( + emergencyUpgradeBoard, + "EmergencyUpgradeBoard", + "1" + ); + } + + bytes memory guardiansSignatures; + { + address[] memory guardiansMembers = new address[](8); + { + IMultisig guardians = IMultisig(_protocolUpgradeHandler.guardians()); + for (uint256 i = 0; i < 8; i++) { + guardiansMembers[i] = guardians.members(i); + } + } + bytes[] memory guardiansRawSignatures = new bytes[](8); + for (uint256 i = 0; i < 8; i++) { + bytes32 safeDigest; + { + bytes32 guardiansDigest = EIP712Utils.buildDigest( + emergencyUpgradeBoardDigest, + keccak256(abi.encode(EXECUTE_EMERGENCY_UPGRADE_GUARDIANS_TYPEHASH, upgradeId)) + ); + safeDigest = ISafe(guardiansMembers[i]).getMessageHash(abi.encode(guardiansDigest)); + } + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(_governorWallet, safeDigest); + guardiansRawSignatures[i] = abi.encodePacked(r, s, v); + } + guardiansSignatures = abi.encode(guardiansMembers, guardiansRawSignatures); + } + + bytes memory securityCouncilSignatures; + { + address[] memory securityCouncilMembers = new address[](12); + { + IMultisig securityCouncil = IMultisig(_protocolUpgradeHandler.securityCouncil()); + for (uint256 i = 0; i < 12; i++) { + securityCouncilMembers[i] = securityCouncil.members(i); + } + } + bytes[] memory securityCouncilRawSignatures = new bytes[](12); + for (uint256 i = 0; i < securityCouncilMembers.length; i++) { + bytes32 safeDigest; + { + bytes32 securityCouncilDigest = EIP712Utils.buildDigest( + emergencyUpgradeBoardDigest, + keccak256(abi.encode(EXECUTE_EMERGENCY_UPGRADE_SECURITY_COUNCIL_TYPEHASH, upgradeId)) + ); + safeDigest = ISafe(securityCouncilMembers[i]).getMessageHash(abi.encode(securityCouncilDigest)); + } + { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(_governorWallet, safeDigest); + securityCouncilRawSignatures[i] = abi.encodePacked(r, s, v); + } + } + securityCouncilSignatures = abi.encode(securityCouncilMembers, securityCouncilRawSignatures); + } + + bytes memory zkFoundationSignature; + { + ISafe zkFoundation; + { + IEmergencyUpgrageBoard emergencyUpgradeBoard = IEmergencyUpgrageBoard( + _protocolUpgradeHandler.emergencyUpgradeBoard() + ); + zkFoundation = ISafe(emergencyUpgradeBoard.ZK_FOUNDATION_SAFE()); + } + bytes32 zkFoundationDigest = EIP712Utils.buildDigest( + emergencyUpgradeBoardDigest, + keccak256(abi.encode(EXECUTE_EMERGENCY_UPGRADE_ZK_FOUNDATION_TYPEHASH, upgradeId)) + ); + bytes32 safeDigest = ISafe(zkFoundation).getMessageHash(abi.encode(zkFoundationDigest)); + { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(_governorWallet, safeDigest); + zkFoundationSignature = abi.encodePacked(r, s, v); + } + } + + { + vm.startBroadcast(); + IEmergencyUpgrageBoard emergencyUpgradeBoard = IEmergencyUpgrageBoard( + _protocolUpgradeHandler.emergencyUpgradeBoard() + ); + // solhint-disable-next-line func-named-parameters + emergencyUpgradeBoard.executeEmergencyUpgrade( + _calls, + _salt, + guardiansSignatures, + securityCouncilSignatures, + zkFoundationSignature + ); + vm.stopBroadcast(); + } + } } diff --git a/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol index 0f2e589f3..518005915 100644 --- a/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol +++ b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol @@ -104,6 +104,7 @@ contract SetupLegacyBridge is Script { function setParamsForDummyBridge() internal { (address l2TokenBeacon, bytes32 l2TokenBeaconHash) = calculateTokenBeaconAddress(); DummyL1ERC20Bridge bridge = DummyL1ERC20Bridge(addresses.erc20BridgeProxy); + vm.broadcast(); bridge.setValues(config.l2SharedBridgeAddress, l2TokenBeacon, l2TokenBeaconHash); } @@ -111,8 +112,8 @@ contract SetupLegacyBridge is Script { internal returns (address tokenBeaconAddress, bytes32 tokenBeaconBytecodeHash) { - bytes memory l2StandardTokenCode = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/contracts/bridge/L2StandardERC20.sol/L2StandardERC20.json" + bytes memory l2StandardTokenCode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/L2StandardERC20.sol/L2StandardERC20.json" ); (address l2StandardToken, ) = calculateL2Create2Address( config.l2SharedBridgeAddress, @@ -121,13 +122,16 @@ contract SetupLegacyBridge is Script { "" ); - bytes memory beaconProxy = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol/BeaconProxy.json" + bytes memory beaconProxy = Utils.readFoundryBytecode("/../l2-contracts/zkout/BeaconProxy.sol/BeaconProxy.json"); + tokenBeaconBytecodeHash = L2ContractHelper.hashL2Bytecode(beaconProxy); + + bytes memory upgradableBeacon = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/UpgradeableBeacon.sol/UpgradeableBeacon.json" ); - (tokenBeaconAddress, tokenBeaconBytecodeHash) = calculateL2Create2Address( + (tokenBeaconAddress, ) = calculateL2Create2Address( config.l2SharedBridgeAddress, - beaconProxy, + upgradableBeacon, bytes32(0), abi.encode(l2StandardToken) ); diff --git a/l1-contracts/deploy-scripts/interfaces/IEmergencyUpgrageBoard.sol b/l1-contracts/deploy-scripts/interfaces/IEmergencyUpgrageBoard.sol new file mode 100644 index 000000000..1f3d0d3d6 --- /dev/null +++ b/l1-contracts/deploy-scripts/interfaces/IEmergencyUpgrageBoard.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {IProtocolUpgradeHandler} from "./IProtocolUpgradeHandler.sol"; + +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +interface IEmergencyUpgrageBoard { + function GUARDIANS() external view returns (address); + + function SECURITY_COUNCIL() external view returns (address); + + function ZK_FOUNDATION_SAFE() external view returns (address); + + function executeEmergencyUpgrade( + IProtocolUpgradeHandler.Call[] calldata _calls, + bytes32 _salt, + bytes calldata _guardiansSignatures, + bytes calldata _securityCouncilSignatures, + bytes calldata _zkFoundationSignatures + ) external; +} diff --git a/l1-contracts/deploy-scripts/interfaces/IMultisig.sol b/l1-contracts/deploy-scripts/interfaces/IMultisig.sol new file mode 100644 index 000000000..2a1dd955d --- /dev/null +++ b/l1-contracts/deploy-scripts/interfaces/IMultisig.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +interface IMultisig { + function members(uint256) external view returns (address); +} diff --git a/l1-contracts/deploy-scripts/interfaces/IProtocolUpgradeHandler.sol b/l1-contracts/deploy-scripts/interfaces/IProtocolUpgradeHandler.sol new file mode 100644 index 000000000..baa48f43f --- /dev/null +++ b/l1-contracts/deploy-scripts/interfaces/IProtocolUpgradeHandler.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +interface IProtocolUpgradeHandler { + /// @dev Represents a call to be made during an upgrade. + /// @param target The address to which the call will be made. + /// @param value The amount of Ether (in wei) to be sent along with the call. + /// @param data The calldata to be executed on the `target` address. + struct Call { + address target; + uint256 value; + bytes data; + } + + /// @dev Defines the structure of an upgrade that is executed by Protocol Upgrade Handler. + /// @param executor The L1 address that is authorized to perform the upgrade execution (if address(0) then anyone). + /// @param calls An array of `Call` structs, each representing a call to be made during the upgrade execution. + /// @param salt A bytes32 value used for creating unique upgrade proposal hashes. + struct UpgradeProposal { + Call[] calls; + address executor; + bytes32 salt; + } + + function emergencyUpgradeBoard() external view returns (address); + + function guardians() external view returns (address); + + function securityCouncil() external view returns (address); +} diff --git a/l1-contracts/deploy-scripts/interfaces/ISafe.sol b/l1-contracts/deploy-scripts/interfaces/ISafe.sol new file mode 100644 index 000000000..82877b3b3 --- /dev/null +++ b/l1-contracts/deploy-scripts/interfaces/ISafe.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +interface ISafe { + function getMessageHash(bytes memory _message) external view returns (bytes32); +} diff --git a/l1-contracts/script-config/.gitkeep b/l1-contracts/script-config/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/l1-contracts/script-config/artifacts/BeaconProxy.json b/l1-contracts/script-config/artifacts/BeaconProxy.json deleted file mode 100644 index 258780377..000000000 --- a/l1-contracts/script-config/artifacts/BeaconProxy.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "_format": "hh-zksolc-artifact-1", - "contractName": "BeaconProxy", - "sourceName": "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "beacon", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "bytecode": "0x0004000000000002000700000000000200000000030100190000006003300270000001020030019d0000010203300197000300000031035500020000000103550000008008000039000000400080043f00000001022001900000001c0000c13d000000000131034f0000010d02000041000000000202041a0000010b04000041000000800040043f00000106022001970000000004000414000000000303004b000000250000c13d000000040320008c000000ab0000c13d0000000103000031000000200230008c00000000040300190000002004008039000000d60000013d0000010302300041000001040220009c0000002c0000213d0000011d0100004100000000001004350000004101000039000000040010043f0000011e010000410000040400010430000000040320008c000001160000c13d0000000103000031000000200230008c00000000040300190000002004008039000001410000013d0000009f023000390000010502200197000000400020043f0000001f0230018f00000005043002720000003b0000613d00000000050000190000000506500210000000000761034f000000000707043b000000800660003900000000007604350000000105500039000000000645004b000000330000413d000000000502004b0000004a0000613d0000000504400210000000000141034f00000003022002100000008004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f00000000001404350000003f0130008c0000014a0000a13d000000800a00043d0000010601a0009c0000014a0000213d000000a00200043d000001070120009c0000014a0000213d0000001f012000390000010804000041000000000531004b000000000500001900000000050480190000010801100197000000000601004b0000000004008019000001080110009c000000000405c019000000000104004b0000014a0000c13d00000080012000390000000001010433000001070410009c0000001f0000213d0000003f04100039000000200700008a000000000474016f000000400900043d0000000004490019000000000594004b00000000050000190000000105004039000001070640009c0000001f0000213d00000001055001900000001f0000c13d0000008003300039000000400040043f0000000006190436000000a0022000390000000004210019000000000334004b0000014a0000213d000600000009001d000500000007001d000400000008001d000000000301004b000000820000613d000000000300001900000000046300190000000005230019000000000505043300000000005404350000002003300039000000000413004b0000007b0000413d000300000006001d000000000116001900000000000104350000010901000041000000000010043900070000000a001d0000000400a0044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000400a00043d000000000101043b000000000101004b000002200000c13d0000006401a000390000011b0200004100000000002104350000004401a000390000011c0200004100000000002104350000002401a0003900000025020000390000000000210435000001150100004100000000001a04350000000401a000390000002002000039000000000021043500000102010000410000010202a0009c000000000a0180190000004001a002100000011a011001c700000404000104300000010201000041000001020340009c0000000004018019000000c0014002100000011f011001c7040203f80000040f000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000000c30000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000000bb0000413d000000000705004b000000d20000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f000300000001035500000001022001900000014c0000613d0000009f02400039000000e00220018f000000400020043f000000200230008c0000014a0000413d000000800200043d000001060420009c0000014a0000213d000000020500036700000000040000310000001f0740018f0000000506400272000000eb0000613d00000000080000190000000509800210000000000a95034f000000000a0a043b0000000000a904350000000108800039000000000968004b000000e40000413d000000000807004b000000f90000613d00000003077002100000000506600210000000000806043300000000087801cf000000000878022f000000000565034f000000000505043b0000010007700089000000000575022f00000000057501cf000000000585019f00000000005604350000000005000414000000040620008c000001c40000c13d0000001f0430018f0000000502300272000001070000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b000001000000413d000000000504004b000001ed0000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000001ed0000013d0000010201000041000001020340009c0000000004018019000000c0014002100000011f011001c7040203f80000040f000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f00000005064002720000012e0000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000001260000413d000000000705004b0000013d0000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000001690000613d0000001f02400039000000600220018f00000080022001bf000000400020043f000000200230008c0000014a0000413d000000800200043d000001060420009c0000018c0000a13d00000000010000190000040400010430000000400200043d0000001f0430018f0000000505300272000001590000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000001510000413d000000000604004b000001680000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d000000400200043d0000001f0430018f0000000505300272000001760000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000016e0000413d000000000604004b000001850000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000010201000041000001020420009c000000000201801900000040012002100000006002300210000000000121019f0000040400010430000000020500036700000000040000310000001f0740018f0000000506400272000001990000613d00000000080000190000000509800210000000000a95034f000000000a0a043b0000000000a904350000000108800039000000000968004b000001920000413d000000000807004b000001a70000613d00000003077002100000000506600210000000000806043300000000087801cf000000000878022f000000000565034f000000000505043b0000010007700089000000000575022f00000000057501cf000000000585019f00000000005604350000000005000414000000040620008c000001ee0000c13d0000001f0430018f0000000502300272000001b50000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b000001ae0000413d000000000504004b000002170000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000002170000013d0000010201000041000001020350009c0000000005018019000001020340009c00000000040180190000006001400210000000c003500210000000000113019f040203fd0000040f0003000000010355000000000301001900000060033002700000001f0430018f000101020030019d00000102033001970000000505300272000001dd0000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000001d60000413d000000000604004b000001eb0000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000001012001900000021c0000613d000002170000013d0000010201000041000001020350009c0000000005018019000001020340009c00000000040180190000006001400210000000c003500210000000000113019f040203fd0000040f0003000000010355000000000301001900000060033002700000001f0430018f000101020030019d00000102033001970000000505300272000002070000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000002000000413d000000000604004b000002150000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000001012001900000021e0000613d0000010201000041000001020230009c00000000030180190000006001300210000004030001042e00000060013002100000040400010430000000600130021000000404000104300000010b0100004100000000001a0435000000000100041400000007020000290000010602200197000000040320008c000700000002001d0000022d0000c13d0000000103000031000000200130008c000000000403001900000020040080390000025e0000013d0000010204000041000001020310009c00000000010480190000010203a0009c00000000040a40190000004003400210000000c001100210000000000131019f0000010c011001c700020000000a001d040203f80000040f000000020a000029000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f00000005064002720000024b0000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000002430000413d000000000705004b0000025a0000613d0000000506600210000000000761034f00000000066a00190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000002950000613d0000001f01400039000000600210018f0000000001a20019000000000221004b00000000020000190000000102004039000001070410009c0000001f0000213d00000001022001900000001f0000c13d000000400010043f000000200130008c0000014a0000413d00000000010a0433000001060210009c0000014a0000213d00000109020000410000000000200439000000040010044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000400200043d000200000002001d000000000101043b000000000101004b000002b20000c13d0000000203000029000000640130003900000118020000410000000000210435000000440130003900000119020000410000000000210435000000240130003900000030020000390000000000210435000001150100004100000000001304350000000401300039000000200200003900000000002104350000010201000041000001020230009c000000000301801900000040013002100000011a011001c70000040400010430000000400200043d0000001f0430018f0000000505300272000002a20000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000029a0000413d000000000604004b000001850000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d0000010d01000041000000000201041a0000010e022001970000000705000029000000000252019f000000000021041b00000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010f011001c70000800d0200003900000002030000390000011004000041040203f30000040f000000010120019000000006010000290000014a0000613d0000000001010433000000000101004b000002cd0000c13d0000002001000039000001000010044300000120000004430000011701000041000004030001042e0000010b010000410000000202000029000000000012043500000000010004140000000702000029000000040220008c000002d90000c13d0000000103000031000000200130008c000000000403001900000020040080390000030b0000013d0000010202000041000001020310009c00000000010280190000000204000029000001020340009c00000000020440190000004002200210000000c001100210000000000121019f0000010c011001c70000000702000029040203f80000040f000000020a000029000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000002f80000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000002f00000413d000000000705004b000003070000613d0000000506600210000000000761034f00000002066000290000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000003380000613d0000001f01400039000000600110018f0000000202100029000000000112004b00000000010000190000000101004039000700000002001d000001070220009c00000006040000290000001f0000213d00000001011001900000001f0000c13d0000000701000029000000400010043f000000200130008c0000014a0000413d00000002010000290000000001010433000200000001001d000001060110009c0000014a0000213d0000000701000029000001110110009c0000001f0000213d00000007050000290000006001500039000000400010043f000000400150003900000112020000410000000000210435000000270100003900000000021504360000011301000041000100000002001d0000000000120435000000000204043300000000010004140000000204000029000000040440008c000003550000c13d0000000102000039000001070130009c00000005050000290000001f0000213d0000036d0000013d000000400200043d0000001f0430018f0000000505300272000003450000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000033d0000413d000000000604004b000003540000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d00000102030000410000000305000029000001020450009c00000000050380190000004004500210000001020520009c00000000020380190000006002200210000000000242019f000001020410009c0000000001038019000000c001100210000000000121019f0000000202000029040203fd0000040f0000006004000039000000010220018f00030000000103550000006001100270000101020010019d000001020310019800000004090000290000000505000029000003960000613d0000003f01300039000000000151016f000000400400043d0000000001140019000000000541004b00000000050000190000000105004039000001070610009c0000001f0000213d00000001055001900000001f0000c13d000000400010043f0000001f0130018f000000000934043600000003050003670000000503300272000003870000613d000000000600001900000005076002100000000008790019000000000775034f000000000707043b00000000007804350000000106600039000000000736004b0000037f0000413d000000000601004b000003960000613d0000000503300210000000000535034f00000000033900190000000301100210000000000603043300000000061601cf000000000616022f000000000505043b0000010001100089000000000515022f00000000011501cf000000000161019f00000000001304350000000001040433000000000202004b000003b60000c13d000000000201004b000003dc0000c13d000000400400043d000600000004001d0000011501000041000000000014043500000004014000390000002002000039000000000021043500000007010000290000000003010433000700000003001d0000002401400039000000000031043500000044024000390000000101000029040203e50000040f00000007010000290000001f01100039000000050110017f00000044011000390000010202000041000001020310009c00000000010280190000000604000029000001020340009c00000000040280190000004002400210000003e20000013d000000000101004b000002c80000c13d000001090100004100000000001004390000000201000029000000040010044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000000101043b000000000101004b000002c80000c13d000000400100043d00000044021000390000011403000041000000000032043500000024021000390000001d030000390000000000320435000001150200004100000000002104350000000402100039000000200300003900000000003204350000010202000041000001020310009c0000000001028019000000400110021000000116011001c70000040400010430000000000001042f0000010202000041000001020310009c0000000001028019000001020390009c000000000902801900000040029002100000006001100210000000000121019f0000040400010430000000000403004b000003ef0000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000534004b000003e80000413d00000000012300190000000000010435000000000001042d000000000001042f000003f6002104210000000102000039000000000001042d0000000002000019000000000001042d000003fb002104230000000102000039000000000001042d0000000002000019000000000001042d00000400002104250000000102000039000000000001042d0000000002000019000000000001042d0000040200000432000004030001042e000004040001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009fffffffffffffffffffffffffffffffffffffffffffffffff000000000000007f00000000000000000000000000000000000000000000000000000001ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff80000000000000000000000000000000000000000000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8302000002000000000000000000000000000000240000000000000000000000005c60da1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000a3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50ffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e000000000000000000000000000000000000000000000000ffffffffffffff9f206661696c656400000000000000000000000000000000000000000000000000416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000008c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000020000000000000000000000000000004000000100000000000000000073206e6f74206120636f6e747261637400000000000000000000000000000000455243313936373a20626561636f6e20696d706c656d656e746174696f6e206900000000000000000000000000000000000000840000000000000000000000007472616374000000000000000000000000000000000000000000000000000000455243313936373a206e657720626561636f6e206973206e6f74206120636f6e4e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000004000000800000000000000000d32177e88b033622e0bc848f24ab73d0795ed87730981120fcdf94fbc134fa5d", - "deployedBytecode": "0x0004000000000002000700000000000200000000030100190000006003300270000001020030019d0000010203300197000300000031035500020000000103550000008008000039000000400080043f00000001022001900000001c0000c13d000000000131034f0000010d02000041000000000202041a0000010b04000041000000800040043f00000106022001970000000004000414000000000303004b000000250000c13d000000040320008c000000ab0000c13d0000000103000031000000200230008c00000000040300190000002004008039000000d60000013d0000010302300041000001040220009c0000002c0000213d0000011d0100004100000000001004350000004101000039000000040010043f0000011e010000410000040400010430000000040320008c000001160000c13d0000000103000031000000200230008c00000000040300190000002004008039000001410000013d0000009f023000390000010502200197000000400020043f0000001f0230018f00000005043002720000003b0000613d00000000050000190000000506500210000000000761034f000000000707043b000000800660003900000000007604350000000105500039000000000645004b000000330000413d000000000502004b0000004a0000613d0000000504400210000000000141034f00000003022002100000008004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f00000000001404350000003f0130008c0000014a0000a13d000000800a00043d0000010601a0009c0000014a0000213d000000a00200043d000001070120009c0000014a0000213d0000001f012000390000010804000041000000000531004b000000000500001900000000050480190000010801100197000000000601004b0000000004008019000001080110009c000000000405c019000000000104004b0000014a0000c13d00000080012000390000000001010433000001070410009c0000001f0000213d0000003f04100039000000200700008a000000000474016f000000400900043d0000000004490019000000000594004b00000000050000190000000105004039000001070640009c0000001f0000213d00000001055001900000001f0000c13d0000008003300039000000400040043f0000000006190436000000a0022000390000000004210019000000000334004b0000014a0000213d000600000009001d000500000007001d000400000008001d000000000301004b000000820000613d000000000300001900000000046300190000000005230019000000000505043300000000005404350000002003300039000000000413004b0000007b0000413d000300000006001d000000000116001900000000000104350000010901000041000000000010043900070000000a001d0000000400a0044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000400a00043d000000000101043b000000000101004b000002200000c13d0000006401a000390000011b0200004100000000002104350000004401a000390000011c0200004100000000002104350000002401a0003900000025020000390000000000210435000001150100004100000000001a04350000000401a000390000002002000039000000000021043500000102010000410000010202a0009c000000000a0180190000004001a002100000011a011001c700000404000104300000010201000041000001020340009c0000000004018019000000c0014002100000011f011001c7040203f80000040f000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000000c30000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000000bb0000413d000000000705004b000000d20000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f000300000001035500000001022001900000014c0000613d0000009f02400039000000e00220018f000000400020043f000000200230008c0000014a0000413d000000800200043d000001060420009c0000014a0000213d000000020500036700000000040000310000001f0740018f0000000506400272000000eb0000613d00000000080000190000000509800210000000000a95034f000000000a0a043b0000000000a904350000000108800039000000000968004b000000e40000413d000000000807004b000000f90000613d00000003077002100000000506600210000000000806043300000000087801cf000000000878022f000000000565034f000000000505043b0000010007700089000000000575022f00000000057501cf000000000585019f00000000005604350000000005000414000000040620008c000001c40000c13d0000001f0430018f0000000502300272000001070000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b000001000000413d000000000504004b000001ed0000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000001ed0000013d0000010201000041000001020340009c0000000004018019000000c0014002100000011f011001c7040203f80000040f000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f00000005064002720000012e0000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000001260000413d000000000705004b0000013d0000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000001690000613d0000001f02400039000000600220018f00000080022001bf000000400020043f000000200230008c0000014a0000413d000000800200043d000001060420009c0000018c0000a13d00000000010000190000040400010430000000400200043d0000001f0430018f0000000505300272000001590000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000001510000413d000000000604004b000001680000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d000000400200043d0000001f0430018f0000000505300272000001760000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000016e0000413d000000000604004b000001850000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000010201000041000001020420009c000000000201801900000040012002100000006002300210000000000121019f0000040400010430000000020500036700000000040000310000001f0740018f0000000506400272000001990000613d00000000080000190000000509800210000000000a95034f000000000a0a043b0000000000a904350000000108800039000000000968004b000001920000413d000000000807004b000001a70000613d00000003077002100000000506600210000000000806043300000000087801cf000000000878022f000000000565034f000000000505043b0000010007700089000000000575022f00000000057501cf000000000585019f00000000005604350000000005000414000000040620008c000001ee0000c13d0000001f0430018f0000000502300272000001b50000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b000001ae0000413d000000000504004b000002170000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000002170000013d0000010201000041000001020350009c0000000005018019000001020340009c00000000040180190000006001400210000000c003500210000000000113019f040203fd0000040f0003000000010355000000000301001900000060033002700000001f0430018f000101020030019d00000102033001970000000505300272000001dd0000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000001d60000413d000000000604004b000001eb0000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000001012001900000021c0000613d000002170000013d0000010201000041000001020350009c0000000005018019000001020340009c00000000040180190000006001400210000000c003500210000000000113019f040203fd0000040f0003000000010355000000000301001900000060033002700000001f0430018f000101020030019d00000102033001970000000505300272000002070000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000002000000413d000000000604004b000002150000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000001012001900000021e0000613d0000010201000041000001020230009c00000000030180190000006001300210000004030001042e00000060013002100000040400010430000000600130021000000404000104300000010b0100004100000000001a0435000000000100041400000007020000290000010602200197000000040320008c000700000002001d0000022d0000c13d0000000103000031000000200130008c000000000403001900000020040080390000025e0000013d0000010204000041000001020310009c00000000010480190000010203a0009c00000000040a40190000004003400210000000c001100210000000000131019f0000010c011001c700020000000a001d040203f80000040f000000020a000029000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f00000005064002720000024b0000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000002430000413d000000000705004b0000025a0000613d0000000506600210000000000761034f00000000066a00190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000002950000613d0000001f01400039000000600210018f0000000001a20019000000000221004b00000000020000190000000102004039000001070410009c0000001f0000213d00000001022001900000001f0000c13d000000400010043f000000200130008c0000014a0000413d00000000010a0433000001060210009c0000014a0000213d00000109020000410000000000200439000000040010044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000400200043d000200000002001d000000000101043b000000000101004b000002b20000c13d0000000203000029000000640130003900000118020000410000000000210435000000440130003900000119020000410000000000210435000000240130003900000030020000390000000000210435000001150100004100000000001304350000000401300039000000200200003900000000002104350000010201000041000001020230009c000000000301801900000040013002100000011a011001c70000040400010430000000400200043d0000001f0430018f0000000505300272000002a20000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000029a0000413d000000000604004b000001850000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d0000010d01000041000000000201041a0000010e022001970000000705000029000000000252019f000000000021041b00000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010f011001c70000800d0200003900000002030000390000011004000041040203f30000040f000000010120019000000006010000290000014a0000613d0000000001010433000000000101004b000002cd0000c13d0000002001000039000001000010044300000120000004430000011701000041000004030001042e0000010b010000410000000202000029000000000012043500000000010004140000000702000029000000040220008c000002d90000c13d0000000103000031000000200130008c000000000403001900000020040080390000030b0000013d0000010202000041000001020310009c00000000010280190000000204000029000001020340009c00000000020440190000004002200210000000c001100210000000000121019f0000010c011001c70000000702000029040203f80000040f000000020a000029000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000002f80000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000002f00000413d000000000705004b000003070000613d0000000506600210000000000761034f00000002066000290000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000003380000613d0000001f01400039000000600110018f0000000202100029000000000112004b00000000010000190000000101004039000700000002001d000001070220009c00000006040000290000001f0000213d00000001011001900000001f0000c13d0000000701000029000000400010043f000000200130008c0000014a0000413d00000002010000290000000001010433000200000001001d000001060110009c0000014a0000213d0000000701000029000001110110009c0000001f0000213d00000007050000290000006001500039000000400010043f000000400150003900000112020000410000000000210435000000270100003900000000021504360000011301000041000100000002001d0000000000120435000000000204043300000000010004140000000204000029000000040440008c000003550000c13d0000000102000039000001070130009c00000005050000290000001f0000213d0000036d0000013d000000400200043d0000001f0430018f0000000505300272000003450000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000033d0000413d000000000604004b000003540000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d00000102030000410000000305000029000001020450009c00000000050380190000004004500210000001020520009c00000000020380190000006002200210000000000242019f000001020410009c0000000001038019000000c001100210000000000121019f0000000202000029040203fd0000040f0000006004000039000000010220018f00030000000103550000006001100270000101020010019d000001020310019800000004090000290000000505000029000003960000613d0000003f01300039000000000151016f000000400400043d0000000001140019000000000541004b00000000050000190000000105004039000001070610009c0000001f0000213d00000001055001900000001f0000c13d000000400010043f0000001f0130018f000000000934043600000003050003670000000503300272000003870000613d000000000600001900000005076002100000000008790019000000000775034f000000000707043b00000000007804350000000106600039000000000736004b0000037f0000413d000000000601004b000003960000613d0000000503300210000000000535034f00000000033900190000000301100210000000000603043300000000061601cf000000000616022f000000000505043b0000010001100089000000000515022f00000000011501cf000000000161019f00000000001304350000000001040433000000000202004b000003b60000c13d000000000201004b000003dc0000c13d000000400400043d000600000004001d0000011501000041000000000014043500000004014000390000002002000039000000000021043500000007010000290000000003010433000700000003001d0000002401400039000000000031043500000044024000390000000101000029040203e50000040f00000007010000290000001f01100039000000050110017f00000044011000390000010202000041000001020310009c00000000010280190000000604000029000001020340009c00000000040280190000004002400210000003e20000013d000000000101004b000002c80000c13d000001090100004100000000001004390000000201000029000000040010044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000000101043b000000000101004b000002c80000c13d000000400100043d00000044021000390000011403000041000000000032043500000024021000390000001d030000390000000000320435000001150200004100000000002104350000000402100039000000200300003900000000003204350000010202000041000001020310009c0000000001028019000000400110021000000116011001c70000040400010430000000000001042f0000010202000041000001020310009c0000000001028019000001020390009c000000000902801900000040029002100000006001100210000000000121019f0000040400010430000000000403004b000003ef0000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000534004b000003e80000413d00000000012300190000000000010435000000000001042d000000000001042f000003f6002104210000000102000039000000000001042d0000000002000019000000000001042d000003fb002104230000000102000039000000000001042d0000000002000019000000000001042d00000400002104250000000102000039000000000001042d0000000002000019000000000001042d0000040200000432000004030001042e000004040001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009fffffffffffffffffffffffffffffffffffffffffffffffff000000000000007f00000000000000000000000000000000000000000000000000000001ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff80000000000000000000000000000000000000000000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8302000002000000000000000000000000000000240000000000000000000000005c60da1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000a3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50ffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e000000000000000000000000000000000000000000000000ffffffffffffff9f206661696c656400000000000000000000000000000000000000000000000000416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000008c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000020000000000000000000000000000004000000100000000000000000073206e6f74206120636f6e747261637400000000000000000000000000000000455243313936373a20626561636f6e20696d706c656d656e746174696f6e206900000000000000000000000000000000000000840000000000000000000000007472616374000000000000000000000000000000000000000000000000000000455243313936373a206e657720626561636f6e206973206e6f74206120636f6e4e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000004000000800000000000000000d32177e88b033622e0bc848f24ab73d0795ed87730981120fcdf94fbc134fa5d", - "linkReferences": {}, - "deployedLinkReferences": {}, - "factoryDeps": {} -} diff --git a/l1-contracts/script-config/artifacts/L2SharedBridge.json b/l1-contracts/script-config/artifacts/L2SharedBridge.json deleted file mode 100644 index a74e5c9ad..000000000 --- a/l1-contracts/script-config/artifacts/L2SharedBridge.json +++ /dev/null @@ -1,262 +0,0 @@ -{ - "_format": "hh-zksolc-artifact-1", - "contractName": "L2SharedBridge", - "sourceName": "contracts/bridge/L2SharedBridge.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_eraChainId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Receiver", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FinalizeDeposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l2Sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l1Receiver", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrawalInitiated", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Sender", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Receiver", - "type": "address" - }, - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "finalizeDeposit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1SharedBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "_l1Bridge", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_l2TokenProxyBytecodeHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_aliasedOwner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Bridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1SharedBridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "l2TokenAddress", - "type": "address" - } - ], - "name": "l1TokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "l1TokenAddress", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - } - ], - "name": "l2TokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l2TokenBeacon", - "outputs": [ - { - "internalType": "contract UpgradeableBeacon", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Receiver", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x0004000000000002001000000000000200000000030100190000006004300270000001a20340019700030000003103550002000000010355000001a20040019d00000001022001900000001d0000c13d0000008002000039000000400020043f000000040230008c000000400000413d000000000201043b000000e002200270000001ab0420009c000000420000213d000001b10420009c0000008a0000213d000001b40120009c000000c10000613d000001b50120009c000000400000c13d0000000001000416000000000101004b000000400000c13d0000000401000039000001d90000013d0000000002000416000000000202004b000000400000c13d000000bf02300039000001a302200197000000400020043f0000001f0230018f00000005043002720000002f0000613d00000000050000190000000506500210000000000761034f000000000707043b000000a00660003900000000007604350000000105500039000000000645004b000000270000413d000000000502004b0000003e0000613d0000000504400210000000000141034f0000000302200210000000a004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f0000000000140435000000200130008c000000640000813d00000000010000190000068300010430000001ac0420009c000000940000213d000001af0420009c000000c60000613d000001b00220009c000000400000c13d0000000002000416000000000202004b000000400000c13d000000040230008a000000600220008c000000400000413d0000000402100370000000000402043b000001b60240009c000000400000213d0000002402100370000000000302043b000001b60230009c000000400000213d0000004401100370000000000201043b000000000102004b000001de0000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000001501000039000000a40010043f000001c501000041000000c40010043f000001c6010000410000068300010430000000a00100043d000000800010043f000000000200041a0000ff0003200190000000ac0000c13d000000ff0320018f000000ff0330008c000000820000613d000000ff012001bf000000000010041b000000ff01000039000000400200043d0000000000120435000001a2010000410000000003000414000001a20430009c0000000003018019000001a20420009c00000000020180190000004001200210000000c002300210000000000112019f000001a8011001c70000800d020000390000000103000039000001a904000041068106770000040f0000000101200190000000400000613d000000800100043d000001400000044300000160001004430000002001000039000001000010044300000001010000390000012000100443000001aa01000041000006820001042e000001b20420009c000001a50000613d000001b30120009c000000400000c13d0000000001000416000000000101004b000000400000c13d000000000100041a0000001001100270000001da0000013d000001ad0420009c000001c90000613d000001ae0220009c000000400000c13d0000000002000416000000000202004b000000400000c13d000000040230008a000000200220008c000000400000413d0000000401100370000000000101043b000001b60210009c000000400000213d068106050000040f000001b601100197000000400200043d0000000000120435000001a201000041000001a20320009c00000000020180190000004001200210000001b7011001c7000006820001042e000000400100043d0000006402100039000001a40300004100000000003204350000004402100039000001a5030000410000000000320435000000240210003900000027030000390000000000320435000001a6020000410000000000210435000000040210003900000020030000390000000000320435000001a202000041000001a20310009c00000000010280190000004001100210000001a7011001c700000683000104300000000001000416000000000101004b000000400000c13d0000000101000039000001d90000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000a00220008c000000400000413d0000000402100370000000000802043b000001b60280009c000000400000213d0000002402100370000000000902043b000001b60290009c000000400000213d0000004402100370000000000a02043b000001b602a0009c000000400000213d0000008402100370000000000202043b000001bd0420009c000000400000213d0000002304200039000001c705000041000000000634004b00000000060000190000000006058019000001c704400197000000000704004b0000000005008019000001c70440009c000000000506c019000000000405004b000000400000c13d0000000404200039000000000441034f000000000504043b000001bd0450009c000000400000213d001000240020003d0000001002500029000000000232004b000000400000213d000b00000005001d000f0000000a001d000e00000009001d000c00000008001d0000006401100370000000000101043b000d00000001001d0000000001000411000001c801100041000001b6011001970000000402000039000000000202041a000001b602200197000000000221004b000001050000613d000000000200041a0000001002200270000001b602200197000000000121004b000002c10000c13d0000000101000039000800000001001d000000000101041a000001b601100197000000a00010043f0000004001000039000900000001001d000000c00010043f000000e00000043f0000006001000039000a00000001001d000000800010043f0000010001000039000000400010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ca011001c700008010020000390681067c0000040f00000001022001900000000f05000029000000400000613d0000000202000039000700000002001d000000000202041a000000000301043b000000400100043d000000a004100039000000000034043500000080031000390000000000230435000000600210003900000000005204350000004002100039000000000300041000000000003204350000002002100039000001cb030000410000000000320435000000a0030000390000000000310435000001cc0310009c000002170000213d000000c003100039000000400030043f000001a204000041000001a20320009c000000000204801900000040022002100000000001010433000001a20310009c00000000010480190000006001100210000000000121019f0000000002000414000001a20320009c0000000002048019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000000101043b000500000001001d000001b601100197000600000001001d00000000001004350000000301000039000400000001001d000000200010043f0000000001000414000001a20210009c000001a201008041000000c001100210000001be011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000000101043b000000000101041a000001b601100198000003ad0000c13d00000000010004140000000702000029000000000402041a0000000802000029000000000202041a000000400300043d000000400530003900000009060000290000000000650435000001b602200197000000200530003900000000002504350000000a02000029000000000023043500000060023000390000000000020435000001c00230009c000002170000213d0000008002300039000000400020043f000000a005300039000001cf060000410000000000650435000000e4053000390000000a060000290000000000650435000000c4053000390000000000450435000000a4043000390000000f0500002900000000005404350000010405300039000000000403043300000000004504350000012405300039000000000604004b0000018a0000613d000000000600001900000000075600190000002006600039000000000836001900000000080804330000000000870435000000000746004b000001830000413d000000000354001900000000000304350000001f03400039000a0020000000920000000a0330017f00000084043000390000000000420435000000c3033000390000000a0430017f0000000003240019000000000443004b00000000040000190000000104004039000001bd0530009c000002170000213d0000000104400190000002170000c13d000000400030043f0000000004020433000001d00540009c0000045f0000413d0000004401300039000001dc02000041000000000021043500000024013000390000000802000039000002b50000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000800220008c000000400000413d0000000402100370000000000202043b000001b60320009c000000400000213d0000002403100370000000000603043b000001b60360009c000000400000213d0000006403100370000000000503043b000001b60350009c000000400000213d000000000300041a0000fffe043001900000021d0000c13d000001e00330019700000102033001bf000000000030041b0000004401100370000000000401043b000000000102004b000002290000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f501000041000000610000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000200220008c000000400000413d0000000401100370000000000101043b000001b60210009c000000400000213d00000000001004350000000301000039000000200010043f00000040020000390000000001000019068106610000040f000000000101041a000001b601100197000000800010043f000001b801000041000006820001042e000f00000002001d000e00000004001d000001b9010000410000000000100439001000000003001d0000000400300443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000001004000029000000400000613d000000400500043d00000024015000390000000f020000290000000000210435000001bb0100004100000000001504350000000001000411000d00000001001d000001b601100197000000040250003900000000001204350000000001000414000000040240008c000002150000613d000001a202000041000001a20310009c0000000001028019000001a20350009c00000000020540190000004002200210000000c001100210000000000121019f000001bc011001c70000000002040019000c00000005001d068106770000040f0000000c05000029000000100400002900000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000002640000613d000001bd0150009c000002400000a13d000001f00100004100000000001004350000004101000039000000040010043f000001ef010000410000068300010430000001a601000041000000800010043f0000002001000039000000840010043f0000002e01000039000000a40010043f000001dd01000041000000c40010043f000001de01000041000000e40010043f000001df010000410000068300010430000000000104004b000002330000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f401000041000000610000013d001000000006001d000f00000004001d000e00000005001d000000000105004b000002870000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f301000041000000610000013d000000400050043f00000000004004350000000301000039000000200010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001be011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000400200043d0000002403200039000000000101043b000000000101041a000001b601100198000002c90000c13d000001a6010000410000000000120435000000040120003900000020040000390000000000410435000000020100003900000000001304350000004401200039000001c3030000410000000000310435000001a201000041000001a20320009c00000000020180190000004001200210000001c4011001c70000068300010430000000400200043d0000001f0430018f0000000505300272000002710000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000002690000413d000000000604004b000002800000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001a201000041000001a20420009c000000000201801900000040012002100000006002300210000000000121019f0000068300010430000001e1013001970000001002200210000001e202200197000000000121019f000000000010041b000001e3010000410000000000100439000000000100041200000004001004430000002400000443000001a2030000410000000001000414000001a20210009c0000000001038019000000c001100210000001e4011001c700008005020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000d00000001001d000001e50100004100000000001004390000000001000414000001a20210009c000001a201008041000000c001100210000001e6011001c70000800b020000390681067c0000040f00000001022001900000059c0000613d000000400200043d000c00000002001d000000000101043b0000000d0110006c0000034d0000c13d000000100100006b0000038f0000c13d0000000c030000290000004401300039000001f2020000410000000000210435000000240130003900000003020000390000000000210435000001a6010000410000000000130435000000040130003900000020020000390000000000210435000001a201000041000001a20230009c00000000030180190000004001300210000001c4011001c70000068300010430000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001c901000041000000610000013d0000002004200039000001bf0500004100000000005404350000000e04000029000000600440021000000000004304350000006001100210000000380320003900000000001304350000004c012000390000000f0300002900000000003104350000004c010000390000000000120435000001c00120009c000002170000213d0000008003200039000000400030043f000001c101000041000c00000003001d0000000000130435000000840120003900000020030000390000000000310435000000a40320003900000000010204330000000000130435000000c403200039000000000401004b000002ef0000613d000000000400001900000000053400190000002004400039000000000624001900000000060604330000000000650435000000000514004b000002e80000413d000000000231001900000000000204350000001f01100039000000200200008a000000000121016f000001a2020000410000000c04000029000001a20340009c0000000003020019000000000304401900000040033002100000004401100039000001a20410009c00000000010280190000006001100210000000000131019f0000000003000414000001a20430009c0000000003028019000000c002300210000000000112019f0000800802000039068106770000040f0000000c0a00002900000000030100190000006003300270000001a203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000003190000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000003110000413d000000000705004b000003280000613d0000000506600210000000000761034f0000000c066000290000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000003720000613d0000001f01400039000000600210018f0000000c01200029000000000221004b00000000020000190000000102004039000001bd0410009c00000010070000290000000e05000029000002170000213d0000000102200190000002170000c13d000000400010043f000000200230008c000000400000413d0000000f020000290000000000210435000001a2020000410000000003000414000001a20430009c0000000003028019000001a20410009c00000000010280190000004001100210000000c002300210000000000112019f000001a8011001c7000001b6065001970000800d020000390000000403000039000001c2040000410000000d05000029000003a80000013d0000000c01000029000001e70110009c000002170000813d0000000c040000290000002401400039000001e8020000410000000000210435000000440140003900000000020004140000006003000039001000000003001d0000000000310435000001e90100004100000000001404350000006401400039000000000001043500000004014000390000000000010435000001a201000041000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000121019f000001ea011001c70000800602000039068106770000040f0000000102200190000003fc0000613d000000000201043b000000000102004b000004380000c13d00000003010003670000000102000031000004010000013d000000400200043d0000001f0430018f00000005053002720000037f0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000003770000413d000000000604004b0000038e0000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d0000000401000039000000000201041a000001d90220019700000010022001af000000000021041b000001f101000041000000000200041a000000000112016f000000000010041b00000002010000390000000c040000290000000000140435000001a2010000410000000002000414000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000112019f000001a8011001c70000800d020000390000000103000039000001a904000041068106770000040f0000000101200190000000400000613d0000000001000019000006820001042e0000000f0110006c000004260000c13d000001b901000041000000000010043900000006010000290000000400100443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000e02000029000000400000613d000000400400043d00000024014000390000000d030000290000000000310435000001da010000410000000000140435000001b602200197001000000004001d0000000401400039000f00000002001d000000000021043500000000010004140000000602000029000000040220008c000003e30000613d000001a202000041000001a20310009c00000000010280190000001004000029000001a20340009c00000000020440190000004002200210000000c001100210000000000121019f000001bc011001c70000000602000029068106770000040f00000000030100190000006003300270000101a20030019d000001a203300197000300000001035500000001022001900000059d0000613d0000001001000029000001bd0110009c000002170000213d0000001004000029000000400040043f0000000d010000290000000000140435000001a2010000410000000002000414000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000112019f000001a8011001c70000000c02000029000001b6052001970000800d020000390000000403000039000001db040000410000000f060000290000000607000029000003a80000013d000300000001035500000000020100190000006002200270000101a20020019d000001a202200197000000400300043d0000001f0420018f00000005052002720000040e0000613d000000000600001900000005076002100000000008730019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000004060000413d000000000604004b0000041d0000613d0000000505500210000000000151034f00000000055300190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001a201000041000001a20430009c0000000003018019000001a20420009c000000000201801900000060012002100000004002300210000000000112019f0000068300010430000000400100043d0000004402100039000001ce030000410000000000320435000000240210003900000007030000290000000000320435000001a6020000410000000000210435000000040210003900000020030000390000000000320435000001a202000041000001a20310009c00000000010280190000004001100210000001c4011001c70000068300010430000000400100043d000001eb0310009c000002170000213d000001b602200197000000840310003900000000002304350000002402100039000001ec0300004100000000003204350000006402100039000000000300041400000020040000390000000000420435000000440210003900000010040000290000000000420435000001e902000041000000000021043500000004021000390000000000020435000001a202000041000001a20430009c0000000003028019000001a20410009c00000000010280190000004001100210000000c002300210000000000121019f000001ed011001c70000800602000039068106770000040f00000001022001900000053c0000613d000000000101043b000000000201004b0000055e0000c13d00000003010003670000000102000031000005410000013d000000c001100210000001d1011001970000004002200210000001d202200041000001d302200197000000000121019f0000006002400210000001d402200197000000000121019f000001d5011001c700008006020000390000000003000019000000000400001900000000050000190000000006000019068106770000040f000300000001035500000000030100190000006003300270000101a20030019d000001a2053001970000003f03500039000001a306300197000000400400043d0000000003460019000000000663004b00000000060000190000000106004039000001bd0730009c000002170000213d0000000106600190000002170000c13d000000400030043f00000000035404360000001f0650003900000005066002720000048f0000613d0000000007000031000000020770036700000000080000190000000509800210000000000a930019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000004870000413d000000000600004b000004910000613d0000001f0650018f00000005055002720000049d0000613d000000000700001900000005087002100000000009830019000000000881034f000000000808043b00000000008904350000000107700039000000000857004b000004950000413d000000000706004b000004ac0000613d0000000505500210000000000151034f00000000055300190000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f00000000001504350000000101200190000005ba0000613d0000000001040433000001c702000041000000200410008c00000000040000190000000004024019000001c701100197000000000501004b000000000200a019000001c70110009c000000000204c019000000000102004b000000400000c13d0000000001030433000800000001001d000001b60110009c000000400000213d000001b901000041000000000010043900000008010000290000000400100443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000f020000290000000b04000029000000400000613d000000400300043d000001d701000041000000000013043500000024053000390000000901000029000300000005001d00000000001504350000000401300039000200000001001d00000000002104350000001f0240018f0000006401300039000900000003001d0000004403300039000100000003001d0000000000430435000000100300002900000002033003670000000504400272000004ee0000613d000000000500001900000005065002100000000007610019000000000663034f000000000606043b00000000006704350000000105500039000000000645004b000004e60000413d000000000502004b000004fd0000613d0000000504400210000000000343034f00000000044100190000000302200210000000000504043300000000052501cf000000000525022f000000000303043b0000010002200089000000000323022f00000000022301cf000000000252019f00000000002404350000000b01100029000000000001043500000000010004140000000802000029000000040220008c0000051e0000613d0000000b020000290000001f022000390000000a0220017f000001a2030000410000000905000029000001a20450009c0000000004030019000000000405401900000040044002100000006402200039000001a20520009c00000000020380190000006002200210000000000224019f000001a20410009c0000000001038019000000c001100210000000000121019f0000000802000029068106770000040f00000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000005db0000613d0000000901000029000001bd0110009c000002170000213d0000000901000029000000400010043f0000000802000029000000050120014f000001b601100198000005f80000c13d000000060100002900000000001004350000000401000029000000200010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001be011001c700008010020000390681067c0000040f00000001022001900000000f03000029000000400000613d000000000101043b000000000201041a000001d902200197000000000232019f000000000021041b000003af0000013d000300000001035500000000020100190000006002200270000101a20020019d000001a202200197000000400300043d0000001f0420018f00000005052002720000054e0000613d000000000600001900000005076002100000000008730019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005460000413d000000000604004b0000055d0000613d0000000505500210000000000151034f00000000055300190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000041d0000013d000001b6031001970000000101000039000000000201041a000001d902200197000000000232019f000000000021041b00000002010000390000000f02000029000000000021041b000001b9010000410000000000100439001000000003001d0000000400300443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000e02000029000000400000613d000000400300043d000001ee010000410000000000130435000c00000003001d0000000401300039000000000021043500000000010004140000001002000029000000040220008c000005960000613d000001a202000041000001a20310009c00000000010280190000000c04000029000001a20340009c00000000020440190000004002200210000000c001100210000000000121019f000001ef011001c70000001002000029068106770000040f00000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000005be0000613d0000000c01000029000001bd0110009c000002170000213d0000000c01000029000000400010043f000003940000013d000000000001042f000000400200043d0000001f0430018f0000000505300272000005aa0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005a20000413d000000000604004b000005b90000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000000400100043d0000004402100039000001d603000041000004290000013d000000400200043d0000001f0430018f0000000505300272000005cb0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005c30000413d000000000604004b000002800000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000000400200043d0000001f0430018f0000000505300272000005e80000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005e00000413d000000000604004b000005f70000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000001a60100004100000009030000290000000000130435000000200100003900000002020000290000000000120435000000070100002900000003020000290000000000120435000001d80100004100000001020000290000000000120435000002bb0000013d0001000000000002000100000001001d0000000101000039000000000301041a000000400100043d00000040021000390000004004000039000000000042043500000060020000390000000002210436000001b603300197000000000032043500000060031000390000000000030435000001f60310009c000006580000813d0000008003100039000000400030043f000001a203000041000001a20420009c000000000203801900000040022002100000000001010433000001a20410009c00000000010380190000006001100210000000000121019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f00000001022001900000065e0000613d0000000202000039000000000202041a000000000301043b000000400100043d000000a0041000390000000000340435000000800310003900000000002304350000000102000029000001b602200197000000600310003900000000002304350000004002100039000000000300041000000000003204350000002002100039000001cb030000410000000000320435000000a0030000390000000000310435000001cc0310009c000006580000213d000000c003100039000000400030043f000001a203000041000001a20420009c000000000203801900000040022002100000000001010433000001a20410009c00000000010380190000006001100210000000000121019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f00000001022001900000065e0000613d000000000101043b000001b601100197000000000001042d000001f00100004100000000001004350000004101000039000000040010043f000001ef01000041000006830001043000000000010000190000068300010430000000000001042f000001a203000041000001a20410009c00000000010380190000004001100210000001a20420009c00000000020380190000006002200210000000000112019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f0000000102200190000006750000613d000000000101043b000000000001042d000000000100001900000683000104300000067a002104210000000102000039000000000001042d0000000002000019000000000001042d0000067f002104230000000102000039000000000001042d0000000002000019000000000001042d0000068100000432000006820001042e0000068300010430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe0616c697a696e6700000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320696e69746908c379a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008400000000000000000000000002000000000000000000000000000000000000200000000000000000000000007f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498000000020000000000000000000000000000008000000100000000000000000000000000000000000000000000000000000000000000000000000000cfe7af7b00000000000000000000000000000000000000000000000000000000f54266a100000000000000000000000000000000000000000000000000000000f54266a200000000000000000000000000000000000000000000000000000000f5f1516800000000000000000000000000000000000000000000000000000000cfe7af7c00000000000000000000000000000000000000000000000000000000d9caed1200000000000000000000000000000000000000000000000000000000a31ee5af00000000000000000000000000000000000000000000000000000000a31ee5b000000000000000000000000000000000000000000000000000000000b852ad36000000000000000000000000000000000000000000000000000000006dde720900000000000000000000000000000000000000000000000000000000969b53da000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000008000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83020000020000000000000000000000000000002400000000000000000000000074f4f547000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff020000000000000000000000000000000000004000000000000000000000000011a2ccc100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f62f84b24000000000000000000000000000000000000000000000000000000002fc3848834aac8e883a2d2a17a7514dc4f2d3dd268089df9b9f5d918259ef3b079680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000416d6f756e742063616e6e6f74206265207a65726f000000000000000000000000000000000000000000000000000000000000640000008000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eeeeffffffffffffffffffffffffffffffffeeef6d710000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000060000000a000000000000000002020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494000000000000000000000000000000000000000000000000ffffffffffffff3f020000000000000000000000000000000000000000000000000000000000000067670000000000000000000000000000000000000000000000000000000000003cda335100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000ffffffff000000000000000000000000000000000000000000000000ffffffff00000000000000000000000001000000000000000000000000000000000000000000000000000000000000006d6b00000000000000000000000000000000000000000000000000000000000095f11a40000000000000000000000000000000000000000000000000000000006d74000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000008c2a993e00000000000000000000000000000000000000000000000000000000b84fba9af218da60d299dc177abd5805e7ac541d2673cbee7808c10017874f634f766572666c6f77000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65640000000000000000000000000000000000000000000000000000000000000000000000000084000000800000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffffff0000000000000000000000000000000000000000010200000000000000000000ffffffffffffffffffffffffffffffffffffffff0000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e02000002000000000000000000000000000000440000000000000000000000009a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b0200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7c010004751688ab9322961547058fd0f36d3edf69880b64cbb2857041d33f4a133cda33511d41a8a5431b1770c5bc0ddd62e1cd30555d16659b89c0d60f4f9f570200000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7b010000691fa4f751f8312bc555242f18ed78cdc9aabc0ea77d7d5a675ee8ac6f02000000000000000000000000000000000000a4000000000000000000000000f2fde38b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6266320000000000000000000000000000000000000000000000000000000000736600000000000000000000000000000000000000000000000000000000000064660000000000000000000000000000000000000000000000000000000000006266000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff800000000000000000000000000000000000000000000000000000000000000000f5cf0be6820df44d868e986d4d5cafabd5702ac45d181a5ac4eb5ed59a001b03", - "deployedBytecode": "0x0004000000000002001000000000000200000000030100190000006004300270000001a20340019700030000003103550002000000010355000001a20040019d00000001022001900000001d0000c13d0000008002000039000000400020043f000000040230008c000000400000413d000000000201043b000000e002200270000001ab0420009c000000420000213d000001b10420009c0000008a0000213d000001b40120009c000000c10000613d000001b50120009c000000400000c13d0000000001000416000000000101004b000000400000c13d0000000401000039000001d90000013d0000000002000416000000000202004b000000400000c13d000000bf02300039000001a302200197000000400020043f0000001f0230018f00000005043002720000002f0000613d00000000050000190000000506500210000000000761034f000000000707043b000000a00660003900000000007604350000000105500039000000000645004b000000270000413d000000000502004b0000003e0000613d0000000504400210000000000141034f0000000302200210000000a004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f0000000000140435000000200130008c000000640000813d00000000010000190000068300010430000001ac0420009c000000940000213d000001af0420009c000000c60000613d000001b00220009c000000400000c13d0000000002000416000000000202004b000000400000c13d000000040230008a000000600220008c000000400000413d0000000402100370000000000402043b000001b60240009c000000400000213d0000002402100370000000000302043b000001b60230009c000000400000213d0000004401100370000000000201043b000000000102004b000001de0000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000001501000039000000a40010043f000001c501000041000000c40010043f000001c6010000410000068300010430000000a00100043d000000800010043f000000000200041a0000ff0003200190000000ac0000c13d000000ff0320018f000000ff0330008c000000820000613d000000ff012001bf000000000010041b000000ff01000039000000400200043d0000000000120435000001a2010000410000000003000414000001a20430009c0000000003018019000001a20420009c00000000020180190000004001200210000000c002300210000000000112019f000001a8011001c70000800d020000390000000103000039000001a904000041068106770000040f0000000101200190000000400000613d000000800100043d000001400000044300000160001004430000002001000039000001000010044300000001010000390000012000100443000001aa01000041000006820001042e000001b20420009c000001a50000613d000001b30120009c000000400000c13d0000000001000416000000000101004b000000400000c13d000000000100041a0000001001100270000001da0000013d000001ad0420009c000001c90000613d000001ae0220009c000000400000c13d0000000002000416000000000202004b000000400000c13d000000040230008a000000200220008c000000400000413d0000000401100370000000000101043b000001b60210009c000000400000213d068106050000040f000001b601100197000000400200043d0000000000120435000001a201000041000001a20320009c00000000020180190000004001200210000001b7011001c7000006820001042e000000400100043d0000006402100039000001a40300004100000000003204350000004402100039000001a5030000410000000000320435000000240210003900000027030000390000000000320435000001a6020000410000000000210435000000040210003900000020030000390000000000320435000001a202000041000001a20310009c00000000010280190000004001100210000001a7011001c700000683000104300000000001000416000000000101004b000000400000c13d0000000101000039000001d90000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000a00220008c000000400000413d0000000402100370000000000802043b000001b60280009c000000400000213d0000002402100370000000000902043b000001b60290009c000000400000213d0000004402100370000000000a02043b000001b602a0009c000000400000213d0000008402100370000000000202043b000001bd0420009c000000400000213d0000002304200039000001c705000041000000000634004b00000000060000190000000006058019000001c704400197000000000704004b0000000005008019000001c70440009c000000000506c019000000000405004b000000400000c13d0000000404200039000000000441034f000000000504043b000001bd0450009c000000400000213d001000240020003d0000001002500029000000000232004b000000400000213d000b00000005001d000f0000000a001d000e00000009001d000c00000008001d0000006401100370000000000101043b000d00000001001d0000000001000411000001c801100041000001b6011001970000000402000039000000000202041a000001b602200197000000000221004b000001050000613d000000000200041a0000001002200270000001b602200197000000000121004b000002c10000c13d0000000101000039000800000001001d000000000101041a000001b601100197000000a00010043f0000004001000039000900000001001d000000c00010043f000000e00000043f0000006001000039000a00000001001d000000800010043f0000010001000039000000400010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ca011001c700008010020000390681067c0000040f00000001022001900000000f05000029000000400000613d0000000202000039000700000002001d000000000202041a000000000301043b000000400100043d000000a004100039000000000034043500000080031000390000000000230435000000600210003900000000005204350000004002100039000000000300041000000000003204350000002002100039000001cb030000410000000000320435000000a0030000390000000000310435000001cc0310009c000002170000213d000000c003100039000000400030043f000001a204000041000001a20320009c000000000204801900000040022002100000000001010433000001a20310009c00000000010480190000006001100210000000000121019f0000000002000414000001a20320009c0000000002048019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000000101043b000500000001001d000001b601100197000600000001001d00000000001004350000000301000039000400000001001d000000200010043f0000000001000414000001a20210009c000001a201008041000000c001100210000001be011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000000101043b000000000101041a000001b601100198000003ad0000c13d00000000010004140000000702000029000000000402041a0000000802000029000000000202041a000000400300043d000000400530003900000009060000290000000000650435000001b602200197000000200530003900000000002504350000000a02000029000000000023043500000060023000390000000000020435000001c00230009c000002170000213d0000008002300039000000400020043f000000a005300039000001cf060000410000000000650435000000e4053000390000000a060000290000000000650435000000c4053000390000000000450435000000a4043000390000000f0500002900000000005404350000010405300039000000000403043300000000004504350000012405300039000000000604004b0000018a0000613d000000000600001900000000075600190000002006600039000000000836001900000000080804330000000000870435000000000746004b000001830000413d000000000354001900000000000304350000001f03400039000a0020000000920000000a0330017f00000084043000390000000000420435000000c3033000390000000a0430017f0000000003240019000000000443004b00000000040000190000000104004039000001bd0530009c000002170000213d0000000104400190000002170000c13d000000400030043f0000000004020433000001d00540009c0000045f0000413d0000004401300039000001dc02000041000000000021043500000024013000390000000802000039000002b50000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000800220008c000000400000413d0000000402100370000000000202043b000001b60320009c000000400000213d0000002403100370000000000603043b000001b60360009c000000400000213d0000006403100370000000000503043b000001b60350009c000000400000213d000000000300041a0000fffe043001900000021d0000c13d000001e00330019700000102033001bf000000000030041b0000004401100370000000000401043b000000000102004b000002290000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f501000041000000610000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000200220008c000000400000413d0000000401100370000000000101043b000001b60210009c000000400000213d00000000001004350000000301000039000000200010043f00000040020000390000000001000019068106610000040f000000000101041a000001b601100197000000800010043f000001b801000041000006820001042e000f00000002001d000e00000004001d000001b9010000410000000000100439001000000003001d0000000400300443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000001004000029000000400000613d000000400500043d00000024015000390000000f020000290000000000210435000001bb0100004100000000001504350000000001000411000d00000001001d000001b601100197000000040250003900000000001204350000000001000414000000040240008c000002150000613d000001a202000041000001a20310009c0000000001028019000001a20350009c00000000020540190000004002200210000000c001100210000000000121019f000001bc011001c70000000002040019000c00000005001d068106770000040f0000000c05000029000000100400002900000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000002640000613d000001bd0150009c000002400000a13d000001f00100004100000000001004350000004101000039000000040010043f000001ef010000410000068300010430000001a601000041000000800010043f0000002001000039000000840010043f0000002e01000039000000a40010043f000001dd01000041000000c40010043f000001de01000041000000e40010043f000001df010000410000068300010430000000000104004b000002330000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f401000041000000610000013d001000000006001d000f00000004001d000e00000005001d000000000105004b000002870000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f301000041000000610000013d000000400050043f00000000004004350000000301000039000000200010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001be011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000400200043d0000002403200039000000000101043b000000000101041a000001b601100198000002c90000c13d000001a6010000410000000000120435000000040120003900000020040000390000000000410435000000020100003900000000001304350000004401200039000001c3030000410000000000310435000001a201000041000001a20320009c00000000020180190000004001200210000001c4011001c70000068300010430000000400200043d0000001f0430018f0000000505300272000002710000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000002690000413d000000000604004b000002800000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001a201000041000001a20420009c000000000201801900000040012002100000006002300210000000000121019f0000068300010430000001e1013001970000001002200210000001e202200197000000000121019f000000000010041b000001e3010000410000000000100439000000000100041200000004001004430000002400000443000001a2030000410000000001000414000001a20210009c0000000001038019000000c001100210000001e4011001c700008005020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000d00000001001d000001e50100004100000000001004390000000001000414000001a20210009c000001a201008041000000c001100210000001e6011001c70000800b020000390681067c0000040f00000001022001900000059c0000613d000000400200043d000c00000002001d000000000101043b0000000d0110006c0000034d0000c13d000000100100006b0000038f0000c13d0000000c030000290000004401300039000001f2020000410000000000210435000000240130003900000003020000390000000000210435000001a6010000410000000000130435000000040130003900000020020000390000000000210435000001a201000041000001a20230009c00000000030180190000004001300210000001c4011001c70000068300010430000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001c901000041000000610000013d0000002004200039000001bf0500004100000000005404350000000e04000029000000600440021000000000004304350000006001100210000000380320003900000000001304350000004c012000390000000f0300002900000000003104350000004c010000390000000000120435000001c00120009c000002170000213d0000008003200039000000400030043f000001c101000041000c00000003001d0000000000130435000000840120003900000020030000390000000000310435000000a40320003900000000010204330000000000130435000000c403200039000000000401004b000002ef0000613d000000000400001900000000053400190000002004400039000000000624001900000000060604330000000000650435000000000514004b000002e80000413d000000000231001900000000000204350000001f01100039000000200200008a000000000121016f000001a2020000410000000c04000029000001a20340009c0000000003020019000000000304401900000040033002100000004401100039000001a20410009c00000000010280190000006001100210000000000131019f0000000003000414000001a20430009c0000000003028019000000c002300210000000000112019f0000800802000039068106770000040f0000000c0a00002900000000030100190000006003300270000001a203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000003190000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000003110000413d000000000705004b000003280000613d0000000506600210000000000761034f0000000c066000290000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000003720000613d0000001f01400039000000600210018f0000000c01200029000000000221004b00000000020000190000000102004039000001bd0410009c00000010070000290000000e05000029000002170000213d0000000102200190000002170000c13d000000400010043f000000200230008c000000400000413d0000000f020000290000000000210435000001a2020000410000000003000414000001a20430009c0000000003028019000001a20410009c00000000010280190000004001100210000000c002300210000000000112019f000001a8011001c7000001b6065001970000800d020000390000000403000039000001c2040000410000000d05000029000003a80000013d0000000c01000029000001e70110009c000002170000813d0000000c040000290000002401400039000001e8020000410000000000210435000000440140003900000000020004140000006003000039001000000003001d0000000000310435000001e90100004100000000001404350000006401400039000000000001043500000004014000390000000000010435000001a201000041000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000121019f000001ea011001c70000800602000039068106770000040f0000000102200190000003fc0000613d000000000201043b000000000102004b000004380000c13d00000003010003670000000102000031000004010000013d000000400200043d0000001f0430018f00000005053002720000037f0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000003770000413d000000000604004b0000038e0000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d0000000401000039000000000201041a000001d90220019700000010022001af000000000021041b000001f101000041000000000200041a000000000112016f000000000010041b00000002010000390000000c040000290000000000140435000001a2010000410000000002000414000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000112019f000001a8011001c70000800d020000390000000103000039000001a904000041068106770000040f0000000101200190000000400000613d0000000001000019000006820001042e0000000f0110006c000004260000c13d000001b901000041000000000010043900000006010000290000000400100443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000e02000029000000400000613d000000400400043d00000024014000390000000d030000290000000000310435000001da010000410000000000140435000001b602200197001000000004001d0000000401400039000f00000002001d000000000021043500000000010004140000000602000029000000040220008c000003e30000613d000001a202000041000001a20310009c00000000010280190000001004000029000001a20340009c00000000020440190000004002200210000000c001100210000000000121019f000001bc011001c70000000602000029068106770000040f00000000030100190000006003300270000101a20030019d000001a203300197000300000001035500000001022001900000059d0000613d0000001001000029000001bd0110009c000002170000213d0000001004000029000000400040043f0000000d010000290000000000140435000001a2010000410000000002000414000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000112019f000001a8011001c70000000c02000029000001b6052001970000800d020000390000000403000039000001db040000410000000f060000290000000607000029000003a80000013d000300000001035500000000020100190000006002200270000101a20020019d000001a202200197000000400300043d0000001f0420018f00000005052002720000040e0000613d000000000600001900000005076002100000000008730019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000004060000413d000000000604004b0000041d0000613d0000000505500210000000000151034f00000000055300190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001a201000041000001a20430009c0000000003018019000001a20420009c000000000201801900000060012002100000004002300210000000000112019f0000068300010430000000400100043d0000004402100039000001ce030000410000000000320435000000240210003900000007030000290000000000320435000001a6020000410000000000210435000000040210003900000020030000390000000000320435000001a202000041000001a20310009c00000000010280190000004001100210000001c4011001c70000068300010430000000400100043d000001eb0310009c000002170000213d000001b602200197000000840310003900000000002304350000002402100039000001ec0300004100000000003204350000006402100039000000000300041400000020040000390000000000420435000000440210003900000010040000290000000000420435000001e902000041000000000021043500000004021000390000000000020435000001a202000041000001a20430009c0000000003028019000001a20410009c00000000010280190000004001100210000000c002300210000000000121019f000001ed011001c70000800602000039068106770000040f00000001022001900000053c0000613d000000000101043b000000000201004b0000055e0000c13d00000003010003670000000102000031000005410000013d000000c001100210000001d1011001970000004002200210000001d202200041000001d302200197000000000121019f0000006002400210000001d402200197000000000121019f000001d5011001c700008006020000390000000003000019000000000400001900000000050000190000000006000019068106770000040f000300000001035500000000030100190000006003300270000101a20030019d000001a2053001970000003f03500039000001a306300197000000400400043d0000000003460019000000000663004b00000000060000190000000106004039000001bd0730009c000002170000213d0000000106600190000002170000c13d000000400030043f00000000035404360000001f0650003900000005066002720000048f0000613d0000000007000031000000020770036700000000080000190000000509800210000000000a930019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000004870000413d000000000600004b000004910000613d0000001f0650018f00000005055002720000049d0000613d000000000700001900000005087002100000000009830019000000000881034f000000000808043b00000000008904350000000107700039000000000857004b000004950000413d000000000706004b000004ac0000613d0000000505500210000000000151034f00000000055300190000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f00000000001504350000000101200190000005ba0000613d0000000001040433000001c702000041000000200410008c00000000040000190000000004024019000001c701100197000000000501004b000000000200a019000001c70110009c000000000204c019000000000102004b000000400000c13d0000000001030433000800000001001d000001b60110009c000000400000213d000001b901000041000000000010043900000008010000290000000400100443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000f020000290000000b04000029000000400000613d000000400300043d000001d701000041000000000013043500000024053000390000000901000029000300000005001d00000000001504350000000401300039000200000001001d00000000002104350000001f0240018f0000006401300039000900000003001d0000004403300039000100000003001d0000000000430435000000100300002900000002033003670000000504400272000004ee0000613d000000000500001900000005065002100000000007610019000000000663034f000000000606043b00000000006704350000000105500039000000000645004b000004e60000413d000000000502004b000004fd0000613d0000000504400210000000000343034f00000000044100190000000302200210000000000504043300000000052501cf000000000525022f000000000303043b0000010002200089000000000323022f00000000022301cf000000000252019f00000000002404350000000b01100029000000000001043500000000010004140000000802000029000000040220008c0000051e0000613d0000000b020000290000001f022000390000000a0220017f000001a2030000410000000905000029000001a20450009c0000000004030019000000000405401900000040044002100000006402200039000001a20520009c00000000020380190000006002200210000000000224019f000001a20410009c0000000001038019000000c001100210000000000121019f0000000802000029068106770000040f00000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000005db0000613d0000000901000029000001bd0110009c000002170000213d0000000901000029000000400010043f0000000802000029000000050120014f000001b601100198000005f80000c13d000000060100002900000000001004350000000401000029000000200010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001be011001c700008010020000390681067c0000040f00000001022001900000000f03000029000000400000613d000000000101043b000000000201041a000001d902200197000000000232019f000000000021041b000003af0000013d000300000001035500000000020100190000006002200270000101a20020019d000001a202200197000000400300043d0000001f0420018f00000005052002720000054e0000613d000000000600001900000005076002100000000008730019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005460000413d000000000604004b0000055d0000613d0000000505500210000000000151034f00000000055300190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000041d0000013d000001b6031001970000000101000039000000000201041a000001d902200197000000000232019f000000000021041b00000002010000390000000f02000029000000000021041b000001b9010000410000000000100439001000000003001d0000000400300443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000e02000029000000400000613d000000400300043d000001ee010000410000000000130435000c00000003001d0000000401300039000000000021043500000000010004140000001002000029000000040220008c000005960000613d000001a202000041000001a20310009c00000000010280190000000c04000029000001a20340009c00000000020440190000004002200210000000c001100210000000000121019f000001ef011001c70000001002000029068106770000040f00000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000005be0000613d0000000c01000029000001bd0110009c000002170000213d0000000c01000029000000400010043f000003940000013d000000000001042f000000400200043d0000001f0430018f0000000505300272000005aa0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005a20000413d000000000604004b000005b90000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000000400100043d0000004402100039000001d603000041000004290000013d000000400200043d0000001f0430018f0000000505300272000005cb0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005c30000413d000000000604004b000002800000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000000400200043d0000001f0430018f0000000505300272000005e80000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005e00000413d000000000604004b000005f70000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000001a60100004100000009030000290000000000130435000000200100003900000002020000290000000000120435000000070100002900000003020000290000000000120435000001d80100004100000001020000290000000000120435000002bb0000013d0001000000000002000100000001001d0000000101000039000000000301041a000000400100043d00000040021000390000004004000039000000000042043500000060020000390000000002210436000001b603300197000000000032043500000060031000390000000000030435000001f60310009c000006580000813d0000008003100039000000400030043f000001a203000041000001a20420009c000000000203801900000040022002100000000001010433000001a20410009c00000000010380190000006001100210000000000121019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f00000001022001900000065e0000613d0000000202000039000000000202041a000000000301043b000000400100043d000000a0041000390000000000340435000000800310003900000000002304350000000102000029000001b602200197000000600310003900000000002304350000004002100039000000000300041000000000003204350000002002100039000001cb030000410000000000320435000000a0030000390000000000310435000001cc0310009c000006580000213d000000c003100039000000400030043f000001a203000041000001a20420009c000000000203801900000040022002100000000001010433000001a20410009c00000000010380190000006001100210000000000121019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f00000001022001900000065e0000613d000000000101043b000001b601100197000000000001042d000001f00100004100000000001004350000004101000039000000040010043f000001ef01000041000006830001043000000000010000190000068300010430000000000001042f000001a203000041000001a20410009c00000000010380190000004001100210000001a20420009c00000000020380190000006002200210000000000112019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f0000000102200190000006750000613d000000000101043b000000000001042d000000000100001900000683000104300000067a002104210000000102000039000000000001042d0000000002000019000000000001042d0000067f002104230000000102000039000000000001042d0000000002000019000000000001042d0000068100000432000006820001042e0000068300010430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe0616c697a696e6700000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320696e69746908c379a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008400000000000000000000000002000000000000000000000000000000000000200000000000000000000000007f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498000000020000000000000000000000000000008000000100000000000000000000000000000000000000000000000000000000000000000000000000cfe7af7b00000000000000000000000000000000000000000000000000000000f54266a100000000000000000000000000000000000000000000000000000000f54266a200000000000000000000000000000000000000000000000000000000f5f1516800000000000000000000000000000000000000000000000000000000cfe7af7c00000000000000000000000000000000000000000000000000000000d9caed1200000000000000000000000000000000000000000000000000000000a31ee5af00000000000000000000000000000000000000000000000000000000a31ee5b000000000000000000000000000000000000000000000000000000000b852ad36000000000000000000000000000000000000000000000000000000006dde720900000000000000000000000000000000000000000000000000000000969b53da000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000008000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83020000020000000000000000000000000000002400000000000000000000000074f4f547000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff020000000000000000000000000000000000004000000000000000000000000011a2ccc100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f62f84b24000000000000000000000000000000000000000000000000000000002fc3848834aac8e883a2d2a17a7514dc4f2d3dd268089df9b9f5d918259ef3b079680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000416d6f756e742063616e6e6f74206265207a65726f000000000000000000000000000000000000000000000000000000000000640000008000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eeeeffffffffffffffffffffffffffffffffeeef6d710000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000060000000a000000000000000002020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494000000000000000000000000000000000000000000000000ffffffffffffff3f020000000000000000000000000000000000000000000000000000000000000067670000000000000000000000000000000000000000000000000000000000003cda335100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000ffffffff000000000000000000000000000000000000000000000000ffffffff00000000000000000000000001000000000000000000000000000000000000000000000000000000000000006d6b00000000000000000000000000000000000000000000000000000000000095f11a40000000000000000000000000000000000000000000000000000000006d74000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000008c2a993e00000000000000000000000000000000000000000000000000000000b84fba9af218da60d299dc177abd5805e7ac541d2673cbee7808c10017874f634f766572666c6f77000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65640000000000000000000000000000000000000000000000000000000000000000000000000084000000800000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffffff0000000000000000000000000000000000000000010200000000000000000000ffffffffffffffffffffffffffffffffffffffff0000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e02000002000000000000000000000000000000440000000000000000000000009a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b0200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7c010004751688ab9322961547058fd0f36d3edf69880b64cbb2857041d33f4a133cda33511d41a8a5431b1770c5bc0ddd62e1cd30555d16659b89c0d60f4f9f570200000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7b010000691fa4f751f8312bc555242f18ed78cdc9aabc0ea77d7d5a675ee8ac6f02000000000000000000000000000000000000a4000000000000000000000000f2fde38b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6266320000000000000000000000000000000000000000000000000000000000736600000000000000000000000000000000000000000000000000000000000064660000000000000000000000000000000000000000000000000000000000006266000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff800000000000000000000000000000000000000000000000000000000000000000f5cf0be6820df44d868e986d4d5cafabd5702ac45d181a5ac4eb5ed59a001b03", - "linkReferences": {}, - "deployedLinkReferences": {}, - "factoryDeps": { - "0x010000691fa4f751f8312bc555242f18ed78cdc9aabc0ea77d7d5a675ee8ac6f": "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol:UpgradeableBeacon", - "0x010004751688ab9322961547058fd0f36d3edf69880b64cbb2857041d33f4a13": "contracts/bridge/L2StandardERC20.sol:L2StandardERC20" - } -} diff --git a/l1-contracts/script-config/artifacts/TransparentUpgradeableProxy.json b/l1-contracts/script-config/artifacts/TransparentUpgradeableProxy.json deleted file mode 100644 index c8880c120..000000000 --- a/l1-contracts/script-config/artifacts/TransparentUpgradeableProxy.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "_format": "hh-zksolc-artifact-1", - "contractName": "TransparentUpgradeableProxy", - "sourceName": "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_logic", - "type": "address" - }, - { - "internalType": "address", - "name": "admin_", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "bytecode": "0x00020000000000020008000000000002000000000301001900000060033002700000012c0330019700010000003103550000008008000039000000400080043f00000001022001900000001e0000c13d000000000431034f00000000050004110000013d02000041000000000702041a0000013002700197000000000603004b000000270000c13d000000000325004b0000010c0000c13d000000000101043b0000014101100197000001420310009c0000001b0000613d000001430310009c000002c20000613d000001440310009c000002680000c13d00000000010004160000000001000019000004ac000104300000012d023000410000012e0220009c0000005f0000213d000001520100004100000000001004350000004101000039000000040010043f0000015301000041000004ac00010430000000000525004b0000012d0000c13d000000000401043b0000014104400197000001420540009c000001670000c13d0000000002000416000000000202004b000002c20000c13d000000240230008c000002c20000413d0000000401100370000000000201043b000001300120009c000002c20000213d000000a001000039000000400010043f000000800000043f00000133010000410000000000100439000800000002001d00000004002004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000002a80000c13d000000400100043d00000064021000390000015403000041000000000032043500000044021000390000015503000041000000000032043500000024021000390000002d0300003900000000003204350000013c0200004100000000002104350000000402100039000000200300003900000000003204350000012c020000410000012c0310009c000000000102801900000040011002100000014c011001c7000004ac000104300000009f023000390000012f02200197000000400020043f0000001f0230018f00000005043002720000006e0000613d00000000050000190000000506500210000000000761034f000000000707043b000000800660003900000000007604350000000105500039000000000645004b000000660000413d000000000502004b0000007d0000613d0000000504400210000000000141034f00000003022002100000008004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f00000000001404350000005f0130008c000002c20000a13d000000800900043d000001300190009c000002c20000213d000000a00700043d000001300170009c000002c20000213d000000c00200043d000001310120009c000002c20000213d0000001f012000390000013204000041000000000531004b000000000500001900000000050480190000013201100197000000000601004b0000000004008019000001320110009c000000000405c019000000000104004b000002c20000c13d00000080012000390000000001010433000001310410009c000000210000213d0000003f04100039000000200a00008a0000000004a4016f000000400b00043d00000000044b00190000000005b4004b00000000050000190000000105004039000001310640009c000000210000213d0000000105500190000000210000c13d0000008003300039000000400040043f00000000061b0436000000a0022000390000000004210019000000000334004b000002c20000213d00060000000b001d00050000000a001d000700000007001d000300000008001d000000000301004b000000b90000613d000000000300001900000000046300190000000005230019000000000505043300000000005404350000002003300039000000000413004b000000b20000413d000400000006001d0000000001160019000000000001043500000133010000410000000000100439000800000009001d00000004009004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000004a0000613d000000080100002900000130051001970000013501000041000000000201041a0000013602200197000000000252019f000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f0000000803000029000000010120019000000007020000290000000605000029000002c20000613d0000000001050433000000000101004b000003770000c13d0000013d01000041000000000301041a0000013004200197000000400100043d0000002002100039000800000004001d0000000000420435000700000003001d000001300230019700000000002104350000012c0200004100000000030004140000012c0430009c00000000030280190000012c0410009c00000000010280190000004001100210000000c002300210000000000112019f0000013e011001c70000800d0200003900000001030000390000013f0400004104aa049b0000040f0000000101200190000002c20000613d000000080100006b0000025a0000613d0000000701000029000001360110019700000008011001af0000013d02000041000000000012041b0000002001000039000001000010044300000120000004430000014001000041000004ab0001042e0000013501000041000000000201041a00000000010004140000013002200197000000040320008c000001e90000c13d00000000030000310000001f0230018f00000005013002720000011e0000613d00000000050000190000000506500210000000000764034f000000000707043b00000000007604350000000105500039000000000615004b000001170000413d000000000502004b0000020e0000613d00000003022002100000000501100210000000000501043300000000052501cf000000000525022f000000000414034f000000000404043b0000010002200089000000000424022f00000000022401cf000000000252019f00000000002104350000020e0000013d0000001f0530018f0000013502000041000000000202041a000001300220019700000005063002720000013b0000613d00000000070000190000000508700210000000000981034f000000000909043b00000000009804350000000107700039000000000867004b000001340000413d000000000705004b000001490000613d00000003055002100000000506600210000000000706043300000000075701cf000000000757022f000000000161034f000000000101043b0000010005500089000000000151022f00000000015101cf000000000171019f00000000001604350000000001000414000000040520008c0000020f0000c13d00000000030000310000001f0230018f0000000501300272000001580000613d00000000050000190000000506500210000000000764034f000000000707043b00000000007604350000000105500039000000000615004b000001510000413d000000000502004b000002360000613d00000003022002100000000501100210000000000501043300000000052501cf000000000525022f000000000414034f000000000404043b0000010002200089000000000424022f00000000022401cf000000000252019f0000000000210435000002360000013d000001430540009c0000023b0000c13d000000440230008c000002c20000413d0000000402100370000000000802043b000001300280009c000002c20000213d0000002402100370000000000402043b000001310240009c000002c20000213d00000023024000390000013205000041000000000632004b000000000600001900000000060580190000013202200197000000000702004b0000000005008019000001320220009c000000000506c019000000000205004b000002c20000c13d0000000405400039000000000251034f000000000202043b000001310620009c000000210000213d000000bf06200039000000200900008a000000000696016f000001310760009c000000210000213d000000400060043f000000800020043f00000000042400190000002404400039000000000334004b000002c20000213d0000002003500039000000000131034f0000001f0320018f00000005042002720000019d0000613d00000000050000190000000506500210000000000761034f000000000707043b000000a00660003900000000007604350000000105500039000000000645004b000001950000413d000700000009001d000000000503004b000001ad0000613d0000000504400210000000000141034f0000000303300210000000a004400039000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f0000000000140435000000a001200039000000000001043500000133010000410000000000100439000800000008001d00000004008004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000004a0000613d0000013501000041000000000201041a000001360220019700000008022001af0000000805000029000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f00000008030000290000000101200190000002c20000613d000000400100043d000600000001001d000001390110009c000000210000213d00000006040000290000006001400039000000400010043f00000040014000390000013a02000041000000000021043500000020014000390000013b02000041000000000021043500000027010000390000000000140435000000800200043d0000000001000414000000040330008c0000040d0000c13d000000010200003900000000040000310000041d0000013d0000012c030000410000012c0410009c0000000001038019000000c00110021004aa04a50000040f0001000000010355000000000301001900000060033002700000001f0430018f0000012c0030019d0000012c033001970000000505300272000001fe0000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000001f70000413d000000000604004b0000020c0000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000000101200190000002640000613d000002360000013d0000012c040000410000012c0510009c0000000001048019000000c0011002100000006003300210000000000131019f04aa04a50000040f0001000000010355000000000301001900000060033002700000001f0430018f0000012c0030019d0000012c033001970000000505300272000002260000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b0000021f0000413d000000000604004b000002340000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000000101200190000002660000613d0000012c010000410000012c0230009c00000000030180190000006001300210000004ab0001042e000001440540009c0000026e0000c13d0000000004000416000000000404004b000002c20000c13d000000240330008c000002c20000413d0000000401100370000000000401043b000001300140009c000002c20000213d000000800020043f000000a00040043f0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000148011001c70000800d020000390000000103000039000700000004001d0000013f04000041000800000007001d04aa049b0000040f000000070400002900000008030000290000000101200190000002c20000613d000000000104004b000002c40000c13d000000400100043d00000064021000390000014a03000041000000000032043500000044021000390000014b03000041000000000032043500000024021000390000002603000039000000530000013d0000006001300210000004ac000104300000006001300210000004ac00010430000001450310009c000002750000c13d0000000001000416000000000101004b000002c20000c13d0000027d0000013d000001450140009c000002840000c13d0000000001000416000000000101004b000002c20000c13d000000a00020043f0000028d0000013d000001460110009c0000029a0000c13d0000000001000416000000000101004b000002c20000c13d0000013501000041000000000101041a0000013002100197000000a00020043f0000002001000039000000800010043f000000c001000039000000400010043f0000015a01000041000004ab0001042e000001460140009c0000029a0000c13d0000000001000416000000000101004b000002c20000c13d0000013501000041000000000101041a0000013001100197000000a00010043f0000002001000039000000800010043f000000c001000039000000400010043f000000800100003900000147020000410000015003000041000001500410009c000000000103801900000040011002100000015101100041000000000121019f000004ab0001042e0000013c01000041000000800010043f0000002001000039000000840010043f0000004201000039000000a40010043f0000015601000041000000c40010043f0000015701000041000000e40010043f0000015801000041000001040010043f0000015901000041000004ac000104300000013501000041000000000201041a000001360220019700000008022001af0000000805000029000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f00000008080000290000000101200190000002c20000613d000000800100043d000000000101004b000002d00000c13d000000400100043d000001490210009c000000210000213d000002cb0000013d0000000001000019000004ac000104300000013601300197000000000114019f0000013d02000041000000000012041b000000400100043d000001490210009c000000210000213d0000002002100039000000400020043f00000000000104350000000002000019000002930000013d000000400900043d000001390190009c000000210000213d0000006001900039000000400010043f00000040019000390000013a02000041000000000021043500000020019000390000013b02000041000000000021043500000027010000390000000000190435000000800200043d0000000001000414000000040380008c000002e40000c13d00000001020000390000000004000031000002f70000013d0000012c030000410000012c0410009c00000000010380190000012c0420009c00000000020380190000006002200210000000c001100210000000000121019f0000014d011001c70000000002080019000700000009001d04aa04a50000040f00000007090000290000000808000029000000010220018f000100000001035500000060011002700000012c0010019d0000012c0410019700000060030000390000008001000039000000000504004b000003230000c13d0000000003030433000000000202004b000003530000c13d000000000203004b0000038c0000c13d000000400100043d0000013c0200004100000000002104350000000402100039000000200300003900000000003204350000000002090433000000240310003900000000002304350000004403100039000000000402004b000003140000613d000000000400001900000000053400190000002004400039000000000694001900000000060604330000000000650435000000000524004b0000030d0000413d0000001f04200039000000200500008a000000000454016f0000000002320019000000000002043500000044024000390000012c030000410000012c0420009c00000000020380190000012c0410009c000000000103801900000040011002100000006002200210000000000112019f000004ac00010430000001310140009c000000210000213d0000003f01400039000000200300008a000000000131016f000000400300043d0000000001130019000000000531004b00000000050000190000000105004039000001310610009c000000210000213d0000000105500190000000210000c13d000000000a090019000000400010043f0000001f0540018f000000000143043600000001060003670000000504400272000003410000613d000000000700001900000005087002100000000009810019000000000886034f000000000808043b00000000008904350000000107700039000000000847004b000003390000413d000000000705004b000000080800002900000000090a0019000002fb0000613d0000000504400210000000000646034f00000000044100190000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000002fb0000013d000000000103004b000002be0000c13d0000013301000041000000000010043900000004008004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000002be0000c13d000000400100043d00000044021000390000014e03000041000000000032043500000024021000390000001d0300003900000000003204350000013c0200004100000000002104350000000402100039000000200300003900000000003204350000012c020000410000012c0310009c000000000102801900000040011002100000014f011001c7000004ac00010430000000400400043d000001390140009c000000210000213d0000006001400039000000400010043f00000040014000390000013a0200004100000000002104350000002701000039000200000004001d00000000021404360000013b01000041000100000002001d000000000012043500000000020504330000000001000414000000040330008c000003950000c13d00000001020000390000000003000031000003a90000013d0000012c020000410000012c0430009c00000000030280190000012c0410009c000000000102801900000040011002100000006002300210000000000112019f000004ac000104300000012c0300004100000004050000290000012c0450009c000000000503801900000040045002100000012c0520009c00000000020380190000006002200210000000000242019f0000012c0410009c0000000001038019000000c001100210000000000112019f000000080200002904aa04a50000040f000000010220018f000100000001035500000060011002700000012c0010019d0000012c031001970000006001000039000000000403004b000003c90000c13d0000000001010433000000000202004b000003f70000c13d000000000201004b000004830000c13d000000400400043d000800000004001d0000013c01000041000000000014043500000004014000390000002002000039000000000021043500000002010000290000000003010433000700000003001d000000240140003900000000003104350000004402400039000000010100002904aa048d0000040f00000007010000290000001f01100039000000050110017f00000044011000390000012c020000410000012c0310009c00000000010280190000000804000029000004870000013d000001310130009c0000000504000029000000210000213d0000003f01300039000000000441016f000000400100043d0000000004410019000000000514004b00000000050000190000000105004039000001310640009c000000210000213d0000000105500190000000210000c13d000000400040043f0000001f0430018f000000000931043600000001050003670000000503300272000003e60000613d000000000600001900000005076002100000000008790019000000000775034f000000000707043b00000000007804350000000106600039000000000736004b000003de0000413d000300000009001d000000000604004b000003ac0000613d0000000503300210000000000535034f00000003033000290000000304400210000000000603043300000000064601cf000000000646022f000000000505043b0000010004400089000000000545022f00000000044501cf000000000464019f0000000000430435000003ac0000013d000000000101004b00000007020000290000000803000029000000e60000c13d0000013301000041000000000010043900000004003004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000000702000029000000e60000c13d000003650000013d0000012c030000410000012c0410009c00000000010380190000012c0420009c00000000020380190000006002200210000000c001100210000000000121019f0000014d011001c7000000080200002904aa04a50000040f000000010220018f000100000001035500000060011002700000012c0010019d0000012c0410019700000060030000390000008001000039000000000504004b0000043e0000c13d0000000003030433000000000202004b0000046b0000c13d000000000203004b0000038c0000c13d000000400100043d0000013c02000041000000000021043500000004021000390000002003000039000000000032043500000006070000290000000002070433000000240310003900000000002304350000004403100039000000000402004b0000043b0000613d000000000400001900000000053400190000002004400039000000000674001900000000060604330000000000650435000000000524004b000004340000413d0000001f042000390000000705000029000003160000013d000001310140009c0000000703000029000000210000213d0000003f01400039000000000131016f000000400300043d0000000001130019000000000531004b00000000050000190000000105004039000001310610009c000000210000213d0000000105500190000000210000c13d000000400010043f0000001f0540018f0000000001430436000000010600036700000005044002720000045b0000613d000000000700001900000005087002100000000009810019000000000886034f000000000808043b00000000008904350000000107700039000000000847004b000004530000413d000000000705004b000004210000613d0000000504400210000000000646034f00000000044100190000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000004210000013d000000000103004b0000047e0000c13d00000133010000410000000000100439000000080100002900000004001004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000003650000613d000000400100043d000001490210009c000000210000213d000002cb0000013d000000000001042f0000012c020000410000012c0310009c000000000102801900000003040000290000012c0340009c000000000402801900000040024002100000006001100210000000000121019f000004ac00010430000000000403004b000004970000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000534004b000004900000413d00000000012300190000000000010435000000000001042d000000000001042f0000049e002104210000000102000039000000000001042d0000000002000019000000000001042d000004a3002104230000000102000039000000000001042d0000000002000019000000000001042d000004a8002104250000000102000039000000000001042d0000000002000019000000000001042d000004aa00000432000004ab0001042e000004ac0001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009fffffffffffffffffffffffffffffffffffffffffffffffff000000000000007f00000000000000000000000000000000000000000000000000000001ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff80000000000000000000000000000000000000000000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcffffffffffffffffffffffff00000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000bc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b000000000000000000000000000000000000000000000000ffffffffffffff9f206661696c656400000000000000000000000000000000000000000000000000416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c08c379a000000000000000000000000000000000000000000000000000000000b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610302000000000000000000000000000000000000400000000000000000000000007e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f0000000200000000000000000000000000000040000001000000000000000000ffffffff000000000000000000000000000000000000000000000000000000003659cfe6000000000000000000000000000000000000000000000000000000004f1ef286000000000000000000000000000000000000000000000000000000008f28397000000000000000000000000000000000000000000000000000000000f851a440000000000000000000000000000000000000000000000000000000005c60da1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000200000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf6464726573730000000000000000000000000000000000000000000000000000455243313936373a206e65772061646d696e20697320746865207a65726f206100000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffdf00000000000000000000000000000000000000000000002000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000006f74206120636f6e747261637400000000000000000000000000000000000000455243313936373a206e657720696d706c656d656e746174696f6e206973206e5472616e73706172656e745570677261646561626c6550726f78793a2061646d696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a40000008000000000000000000000000000000000000000000000000000000020000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000007444ff0b02dc9864c7dbf97ccd7719c286d6972190eeb0285ea9e04a713977c0", - "deployedBytecode": "0x00020000000000020008000000000002000000000301001900000060033002700000012c0330019700010000003103550000008008000039000000400080043f00000001022001900000001e0000c13d000000000431034f00000000050004110000013d02000041000000000702041a0000013002700197000000000603004b000000270000c13d000000000325004b0000010c0000c13d000000000101043b0000014101100197000001420310009c0000001b0000613d000001430310009c000002c20000613d000001440310009c000002680000c13d00000000010004160000000001000019000004ac000104300000012d023000410000012e0220009c0000005f0000213d000001520100004100000000001004350000004101000039000000040010043f0000015301000041000004ac00010430000000000525004b0000012d0000c13d000000000401043b0000014104400197000001420540009c000001670000c13d0000000002000416000000000202004b000002c20000c13d000000240230008c000002c20000413d0000000401100370000000000201043b000001300120009c000002c20000213d000000a001000039000000400010043f000000800000043f00000133010000410000000000100439000800000002001d00000004002004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000002a80000c13d000000400100043d00000064021000390000015403000041000000000032043500000044021000390000015503000041000000000032043500000024021000390000002d0300003900000000003204350000013c0200004100000000002104350000000402100039000000200300003900000000003204350000012c020000410000012c0310009c000000000102801900000040011002100000014c011001c7000004ac000104300000009f023000390000012f02200197000000400020043f0000001f0230018f00000005043002720000006e0000613d00000000050000190000000506500210000000000761034f000000000707043b000000800660003900000000007604350000000105500039000000000645004b000000660000413d000000000502004b0000007d0000613d0000000504400210000000000141034f00000003022002100000008004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f00000000001404350000005f0130008c000002c20000a13d000000800900043d000001300190009c000002c20000213d000000a00700043d000001300170009c000002c20000213d000000c00200043d000001310120009c000002c20000213d0000001f012000390000013204000041000000000531004b000000000500001900000000050480190000013201100197000000000601004b0000000004008019000001320110009c000000000405c019000000000104004b000002c20000c13d00000080012000390000000001010433000001310410009c000000210000213d0000003f04100039000000200a00008a0000000004a4016f000000400b00043d00000000044b00190000000005b4004b00000000050000190000000105004039000001310640009c000000210000213d0000000105500190000000210000c13d0000008003300039000000400040043f00000000061b0436000000a0022000390000000004210019000000000334004b000002c20000213d00060000000b001d00050000000a001d000700000007001d000300000008001d000000000301004b000000b90000613d000000000300001900000000046300190000000005230019000000000505043300000000005404350000002003300039000000000413004b000000b20000413d000400000006001d0000000001160019000000000001043500000133010000410000000000100439000800000009001d00000004009004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000004a0000613d000000080100002900000130051001970000013501000041000000000201041a0000013602200197000000000252019f000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f0000000803000029000000010120019000000007020000290000000605000029000002c20000613d0000000001050433000000000101004b000003770000c13d0000013d01000041000000000301041a0000013004200197000000400100043d0000002002100039000800000004001d0000000000420435000700000003001d000001300230019700000000002104350000012c0200004100000000030004140000012c0430009c00000000030280190000012c0410009c00000000010280190000004001100210000000c002300210000000000112019f0000013e011001c70000800d0200003900000001030000390000013f0400004104aa049b0000040f0000000101200190000002c20000613d000000080100006b0000025a0000613d0000000701000029000001360110019700000008011001af0000013d02000041000000000012041b0000002001000039000001000010044300000120000004430000014001000041000004ab0001042e0000013501000041000000000201041a00000000010004140000013002200197000000040320008c000001e90000c13d00000000030000310000001f0230018f00000005013002720000011e0000613d00000000050000190000000506500210000000000764034f000000000707043b00000000007604350000000105500039000000000615004b000001170000413d000000000502004b0000020e0000613d00000003022002100000000501100210000000000501043300000000052501cf000000000525022f000000000414034f000000000404043b0000010002200089000000000424022f00000000022401cf000000000252019f00000000002104350000020e0000013d0000001f0530018f0000013502000041000000000202041a000001300220019700000005063002720000013b0000613d00000000070000190000000508700210000000000981034f000000000909043b00000000009804350000000107700039000000000867004b000001340000413d000000000705004b000001490000613d00000003055002100000000506600210000000000706043300000000075701cf000000000757022f000000000161034f000000000101043b0000010005500089000000000151022f00000000015101cf000000000171019f00000000001604350000000001000414000000040520008c0000020f0000c13d00000000030000310000001f0230018f0000000501300272000001580000613d00000000050000190000000506500210000000000764034f000000000707043b00000000007604350000000105500039000000000615004b000001510000413d000000000502004b000002360000613d00000003022002100000000501100210000000000501043300000000052501cf000000000525022f000000000414034f000000000404043b0000010002200089000000000424022f00000000022401cf000000000252019f0000000000210435000002360000013d000001430540009c0000023b0000c13d000000440230008c000002c20000413d0000000402100370000000000802043b000001300280009c000002c20000213d0000002402100370000000000402043b000001310240009c000002c20000213d00000023024000390000013205000041000000000632004b000000000600001900000000060580190000013202200197000000000702004b0000000005008019000001320220009c000000000506c019000000000205004b000002c20000c13d0000000405400039000000000251034f000000000202043b000001310620009c000000210000213d000000bf06200039000000200900008a000000000696016f000001310760009c000000210000213d000000400060043f000000800020043f00000000042400190000002404400039000000000334004b000002c20000213d0000002003500039000000000131034f0000001f0320018f00000005042002720000019d0000613d00000000050000190000000506500210000000000761034f000000000707043b000000a00660003900000000007604350000000105500039000000000645004b000001950000413d000700000009001d000000000503004b000001ad0000613d0000000504400210000000000141034f0000000303300210000000a004400039000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f0000000000140435000000a001200039000000000001043500000133010000410000000000100439000800000008001d00000004008004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000004a0000613d0000013501000041000000000201041a000001360220019700000008022001af0000000805000029000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f00000008030000290000000101200190000002c20000613d000000400100043d000600000001001d000001390110009c000000210000213d00000006040000290000006001400039000000400010043f00000040014000390000013a02000041000000000021043500000020014000390000013b02000041000000000021043500000027010000390000000000140435000000800200043d0000000001000414000000040330008c0000040d0000c13d000000010200003900000000040000310000041d0000013d0000012c030000410000012c0410009c0000000001038019000000c00110021004aa04a50000040f0001000000010355000000000301001900000060033002700000001f0430018f0000012c0030019d0000012c033001970000000505300272000001fe0000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000001f70000413d000000000604004b0000020c0000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000000101200190000002640000613d000002360000013d0000012c040000410000012c0510009c0000000001048019000000c0011002100000006003300210000000000131019f04aa04a50000040f0001000000010355000000000301001900000060033002700000001f0430018f0000012c0030019d0000012c033001970000000505300272000002260000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b0000021f0000413d000000000604004b000002340000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000000101200190000002660000613d0000012c010000410000012c0230009c00000000030180190000006001300210000004ab0001042e000001440540009c0000026e0000c13d0000000004000416000000000404004b000002c20000c13d000000240330008c000002c20000413d0000000401100370000000000401043b000001300140009c000002c20000213d000000800020043f000000a00040043f0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000148011001c70000800d020000390000000103000039000700000004001d0000013f04000041000800000007001d04aa049b0000040f000000070400002900000008030000290000000101200190000002c20000613d000000000104004b000002c40000c13d000000400100043d00000064021000390000014a03000041000000000032043500000044021000390000014b03000041000000000032043500000024021000390000002603000039000000530000013d0000006001300210000004ac000104300000006001300210000004ac00010430000001450310009c000002750000c13d0000000001000416000000000101004b000002c20000c13d0000027d0000013d000001450140009c000002840000c13d0000000001000416000000000101004b000002c20000c13d000000a00020043f0000028d0000013d000001460110009c0000029a0000c13d0000000001000416000000000101004b000002c20000c13d0000013501000041000000000101041a0000013002100197000000a00020043f0000002001000039000000800010043f000000c001000039000000400010043f0000015a01000041000004ab0001042e000001460140009c0000029a0000c13d0000000001000416000000000101004b000002c20000c13d0000013501000041000000000101041a0000013001100197000000a00010043f0000002001000039000000800010043f000000c001000039000000400010043f000000800100003900000147020000410000015003000041000001500410009c000000000103801900000040011002100000015101100041000000000121019f000004ab0001042e0000013c01000041000000800010043f0000002001000039000000840010043f0000004201000039000000a40010043f0000015601000041000000c40010043f0000015701000041000000e40010043f0000015801000041000001040010043f0000015901000041000004ac000104300000013501000041000000000201041a000001360220019700000008022001af0000000805000029000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f00000008080000290000000101200190000002c20000613d000000800100043d000000000101004b000002d00000c13d000000400100043d000001490210009c000000210000213d000002cb0000013d0000000001000019000004ac000104300000013601300197000000000114019f0000013d02000041000000000012041b000000400100043d000001490210009c000000210000213d0000002002100039000000400020043f00000000000104350000000002000019000002930000013d000000400900043d000001390190009c000000210000213d0000006001900039000000400010043f00000040019000390000013a02000041000000000021043500000020019000390000013b02000041000000000021043500000027010000390000000000190435000000800200043d0000000001000414000000040380008c000002e40000c13d00000001020000390000000004000031000002f70000013d0000012c030000410000012c0410009c00000000010380190000012c0420009c00000000020380190000006002200210000000c001100210000000000121019f0000014d011001c70000000002080019000700000009001d04aa04a50000040f00000007090000290000000808000029000000010220018f000100000001035500000060011002700000012c0010019d0000012c0410019700000060030000390000008001000039000000000504004b000003230000c13d0000000003030433000000000202004b000003530000c13d000000000203004b0000038c0000c13d000000400100043d0000013c0200004100000000002104350000000402100039000000200300003900000000003204350000000002090433000000240310003900000000002304350000004403100039000000000402004b000003140000613d000000000400001900000000053400190000002004400039000000000694001900000000060604330000000000650435000000000524004b0000030d0000413d0000001f04200039000000200500008a000000000454016f0000000002320019000000000002043500000044024000390000012c030000410000012c0420009c00000000020380190000012c0410009c000000000103801900000040011002100000006002200210000000000112019f000004ac00010430000001310140009c000000210000213d0000003f01400039000000200300008a000000000131016f000000400300043d0000000001130019000000000531004b00000000050000190000000105004039000001310610009c000000210000213d0000000105500190000000210000c13d000000000a090019000000400010043f0000001f0540018f000000000143043600000001060003670000000504400272000003410000613d000000000700001900000005087002100000000009810019000000000886034f000000000808043b00000000008904350000000107700039000000000847004b000003390000413d000000000705004b000000080800002900000000090a0019000002fb0000613d0000000504400210000000000646034f00000000044100190000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000002fb0000013d000000000103004b000002be0000c13d0000013301000041000000000010043900000004008004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000002be0000c13d000000400100043d00000044021000390000014e03000041000000000032043500000024021000390000001d0300003900000000003204350000013c0200004100000000002104350000000402100039000000200300003900000000003204350000012c020000410000012c0310009c000000000102801900000040011002100000014f011001c7000004ac00010430000000400400043d000001390140009c000000210000213d0000006001400039000000400010043f00000040014000390000013a0200004100000000002104350000002701000039000200000004001d00000000021404360000013b01000041000100000002001d000000000012043500000000020504330000000001000414000000040330008c000003950000c13d00000001020000390000000003000031000003a90000013d0000012c020000410000012c0430009c00000000030280190000012c0410009c000000000102801900000040011002100000006002300210000000000112019f000004ac000104300000012c0300004100000004050000290000012c0450009c000000000503801900000040045002100000012c0520009c00000000020380190000006002200210000000000242019f0000012c0410009c0000000001038019000000c001100210000000000112019f000000080200002904aa04a50000040f000000010220018f000100000001035500000060011002700000012c0010019d0000012c031001970000006001000039000000000403004b000003c90000c13d0000000001010433000000000202004b000003f70000c13d000000000201004b000004830000c13d000000400400043d000800000004001d0000013c01000041000000000014043500000004014000390000002002000039000000000021043500000002010000290000000003010433000700000003001d000000240140003900000000003104350000004402400039000000010100002904aa048d0000040f00000007010000290000001f01100039000000050110017f00000044011000390000012c020000410000012c0310009c00000000010280190000000804000029000004870000013d000001310130009c0000000504000029000000210000213d0000003f01300039000000000441016f000000400100043d0000000004410019000000000514004b00000000050000190000000105004039000001310640009c000000210000213d0000000105500190000000210000c13d000000400040043f0000001f0430018f000000000931043600000001050003670000000503300272000003e60000613d000000000600001900000005076002100000000008790019000000000775034f000000000707043b00000000007804350000000106600039000000000736004b000003de0000413d000300000009001d000000000604004b000003ac0000613d0000000503300210000000000535034f00000003033000290000000304400210000000000603043300000000064601cf000000000646022f000000000505043b0000010004400089000000000545022f00000000044501cf000000000464019f0000000000430435000003ac0000013d000000000101004b00000007020000290000000803000029000000e60000c13d0000013301000041000000000010043900000004003004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000000702000029000000e60000c13d000003650000013d0000012c030000410000012c0410009c00000000010380190000012c0420009c00000000020380190000006002200210000000c001100210000000000121019f0000014d011001c7000000080200002904aa04a50000040f000000010220018f000100000001035500000060011002700000012c0010019d0000012c0410019700000060030000390000008001000039000000000504004b0000043e0000c13d0000000003030433000000000202004b0000046b0000c13d000000000203004b0000038c0000c13d000000400100043d0000013c02000041000000000021043500000004021000390000002003000039000000000032043500000006070000290000000002070433000000240310003900000000002304350000004403100039000000000402004b0000043b0000613d000000000400001900000000053400190000002004400039000000000674001900000000060604330000000000650435000000000524004b000004340000413d0000001f042000390000000705000029000003160000013d000001310140009c0000000703000029000000210000213d0000003f01400039000000000131016f000000400300043d0000000001130019000000000531004b00000000050000190000000105004039000001310610009c000000210000213d0000000105500190000000210000c13d000000400010043f0000001f0540018f0000000001430436000000010600036700000005044002720000045b0000613d000000000700001900000005087002100000000009810019000000000886034f000000000808043b00000000008904350000000107700039000000000847004b000004530000413d000000000705004b000004210000613d0000000504400210000000000646034f00000000044100190000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000004210000013d000000000103004b0000047e0000c13d00000133010000410000000000100439000000080100002900000004001004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000003650000613d000000400100043d000001490210009c000000210000213d000002cb0000013d000000000001042f0000012c020000410000012c0310009c000000000102801900000003040000290000012c0340009c000000000402801900000040024002100000006001100210000000000121019f000004ac00010430000000000403004b000004970000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000534004b000004900000413d00000000012300190000000000010435000000000001042d000000000001042f0000049e002104210000000102000039000000000001042d0000000002000019000000000001042d000004a3002104230000000102000039000000000001042d0000000002000019000000000001042d000004a8002104250000000102000039000000000001042d0000000002000019000000000001042d000004aa00000432000004ab0001042e000004ac0001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009fffffffffffffffffffffffffffffffffffffffffffffffff000000000000007f00000000000000000000000000000000000000000000000000000001ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff80000000000000000000000000000000000000000000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcffffffffffffffffffffffff00000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000bc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b000000000000000000000000000000000000000000000000ffffffffffffff9f206661696c656400000000000000000000000000000000000000000000000000416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c08c379a000000000000000000000000000000000000000000000000000000000b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610302000000000000000000000000000000000000400000000000000000000000007e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f0000000200000000000000000000000000000040000001000000000000000000ffffffff000000000000000000000000000000000000000000000000000000003659cfe6000000000000000000000000000000000000000000000000000000004f1ef286000000000000000000000000000000000000000000000000000000008f28397000000000000000000000000000000000000000000000000000000000f851a440000000000000000000000000000000000000000000000000000000005c60da1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000200000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf6464726573730000000000000000000000000000000000000000000000000000455243313936373a206e65772061646d696e20697320746865207a65726f206100000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffdf00000000000000000000000000000000000000000000002000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000006f74206120636f6e747261637400000000000000000000000000000000000000455243313936373a206e657720696d706c656d656e746174696f6e206973206e5472616e73706172656e745570677261646561626c6550726f78793a2061646d696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a40000008000000000000000000000000000000000000000000000000000000020000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000007444ff0b02dc9864c7dbf97ccd7719c286d6972190eeb0285ea9e04a713977c0", - "linkReferences": {}, - "deployedLinkReferences": {}, - "factoryDeps": {} -} diff --git a/l1-contracts/src.ts/deploy.ts b/l1-contracts/src.ts/deploy.ts index d131d269c..c32c79c88 100644 --- a/l1-contracts/src.ts/deploy.ts +++ b/l1-contracts/src.ts/deploy.ts @@ -212,21 +212,11 @@ export class Deployer { public async deployChainAdmin(create2Salt: string, ethTxOptions: ethers.providers.TransactionRequest) { ethTxOptions.gasLimit ??= 10_000_000; - // Firstly, we deploy the access control restriction for the chain admin - const accessControlRestriction = await this.deployViaCreate2( - "AccessControlRestriction", - [0, this.ownerAddress], - create2Salt, - ethTxOptions - ); - if (this.verbose) { - console.log(`CONTRACTS_ACCESS_CONTROL_RESTRICTION_ADDR=${accessControlRestriction}`); - } - // Then we deploy the ChainAdmin contract itself + // We deploy the ChainAdmin contract itself const contractAddress = await this.deployViaCreate2( "ChainAdmin", - [[accessControlRestriction]], + [this.ownerAddress, ethers.constants.AddressZero], create2Salt, ethTxOptions ); diff --git a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol index 910350041..43826e6ac 100644 --- a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol @@ -339,11 +339,7 @@ contract ExperimentalBridgeTest is Test { bridgeHub.addToken(randomAddress); } - function test_addToken_cannotBeCalledByRandomAddress( - address randomAddress, - address randomCaller, - uint256 randomValue - ) public useRandomToken(randomValue) { + function test_addToken_cannotBeCalledByRandomAddress(address randomAddress, address randomCaller) public { vm.assume(randomCaller != bridgeOwner); vm.assume(randomCaller != bridgeHub.admin()); diff --git a/l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol deleted file mode 100644 index e5b45975f..000000000 --- a/l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol +++ /dev/null @@ -1,186 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {Test} from "forge-std/Test.sol"; - -import "openzeppelin-contracts/contracts/utils/Strings.sol"; -import "forge-std/console.sol"; -import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; -import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; -import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; -import {IAccessControlRestriction} from "contracts/governance/IAccessControlRestriction.sol"; -import {Utils} from "test/foundry/unit/concrete/Utils/Utils.sol"; -import {NoCallsProvided, AccessToFallbackDenied, AccessToFunctionDenied} from "contracts/common/L1ContractErrors.sol"; -import {Call} from "contracts/governance/Common.sol"; - -contract AccessRestrictionTest is Test { - AccessControlRestriction internal restriction; - ChainAdmin internal chainAdmin; - address owner; - address randomCaller; - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - function getChainAdminSelectors() public pure returns (bytes4[] memory) { - bytes4[] memory selectors = new bytes4[](12); - selectors[0] = IChainAdmin.getRestrictions.selector; - selectors[1] = IChainAdmin.isRestrictionActive.selector; - selectors[2] = IChainAdmin.addRestriction.selector; - selectors[3] = IChainAdmin.removeRestriction.selector; - - return selectors; - } - - function setUp() public { - owner = makeAddr("random address"); - randomCaller = makeAddr("random caller"); - - restriction = new AccessControlRestriction(0, owner); - address[] memory restrictions = new address[](1); - restrictions[0] = address(restriction); - - chainAdmin = new ChainAdmin(restrictions); - } - - function test_adminAsAddressZero() public { - vm.expectRevert("AccessControl: 0 default admin"); - new AccessControlRestriction(0, address(0)); - } - - function test_setRequiredRoleForCallByNotDefaultAdmin(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); - string memory revertMsg = string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(randomCaller), 20), - " is missing role ", - Strings.toHexString(uint256(DEFAULT_ADMIN_ROLE), 32) - ) - ); - - vm.expectRevert(bytes(revertMsg)); - vm.prank(randomCaller); - restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); - } - - function test_setRequiredRoleForCallAccessToFunctionDenied(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); - - vm.startPrank(owner); - restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); - vm.stopPrank(); - - Call memory call = Call({ - target: address(chainAdmin), - value: 0, - data: abi.encodeCall(IChainAdmin.getRestrictions, ()) - }); - - vm.expectRevert( - abi.encodeWithSelector( - AccessToFunctionDenied.selector, - address(chainAdmin), - chainAdminSelectors[0], - randomCaller - ) - ); - restriction.validateCall(call, randomCaller); - } - - function test_setRequiredRoleForCall(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); - - vm.expectEmit(true, true, false, true); - emit IAccessControlRestriction.RoleSet(address(chainAdmin), chainAdminSelectors[0], role); - - vm.startPrank(owner); - restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); - restriction.grantRole(role, randomCaller); - vm.stopPrank(); - - Call memory call = Call({ - target: address(chainAdmin), - value: 0, - data: abi.encodeCall(IChainAdmin.getRestrictions, ()) - }); - restriction.validateCall(call, randomCaller); - } - - function test_setRequiredRoleForFallbackByNotDefaultAdmin(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - string memory revertMsg = string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(randomCaller), 20), - " is missing role ", - Strings.toHexString(uint256(DEFAULT_ADMIN_ROLE), 32) - ) - ); - - vm.expectRevert(bytes(revertMsg)); - vm.prank(randomCaller); - restriction.setRequiredRoleForFallback(address(chainAdmin), role); - } - - function test_setRequiredRoleForFallbackAccessToFallbackDenied(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - vm.startPrank(owner); - restriction.setRequiredRoleForFallback(address(chainAdmin), role); - vm.stopPrank(); - - Call memory call = Call({target: address(chainAdmin), value: 0, data: ""}); - - vm.expectRevert(abi.encodeWithSelector(AccessToFallbackDenied.selector, address(chainAdmin), randomCaller)); - restriction.validateCall(call, randomCaller); - } - - function test_setRequiredRoleForFallback(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - vm.expectEmit(true, false, false, true); - emit IAccessControlRestriction.FallbackRoleSet(address(chainAdmin), role); - - vm.startPrank(owner); - restriction.setRequiredRoleForFallback(address(chainAdmin), role); - restriction.grantRole(role, randomCaller); - vm.stopPrank(); - - Call memory call = Call({target: address(chainAdmin), value: 0, data: ""}); - restriction.validateCall(call, randomCaller); - } - - function test_validateCallFunction(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); - vm.startPrank(owner); - restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); - restriction.grantRole(role, randomCaller); - vm.stopPrank(); - - Call memory call = Call({ - target: address(chainAdmin), - value: 0, - data: abi.encodeCall(IChainAdmin.getRestrictions, ()) - }); - restriction.validateCall(call, randomCaller); - } - - function test_validateCallFallback(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - vm.startPrank(owner); - restriction.setRequiredRoleForFallback(address(chainAdmin), role); - restriction.grantRole(role, randomCaller); - vm.stopPrank(); - - Call memory call = Call({target: address(chainAdmin), value: 0, data: ""}); - restriction.validateCall(call, randomCaller); - } -} diff --git a/l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol index 01a3c7dfd..735d54328 100644 --- a/l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.24; import {Test} from "forge-std/Test.sol"; import "openzeppelin-contracts/contracts/utils/Strings.sol"; -import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; import {GettersFacet} from "contracts/state-transition/chain-deps/facets/Getters.sol"; @@ -14,7 +13,6 @@ import {Utils} from "test/foundry/unit/concrete/Utils/Utils.sol"; contract ChainAdminTest is Test { ChainAdmin internal chainAdmin; - AccessControlRestriction internal restriction; GettersFacet internal gettersFacet; address internal owner; @@ -26,69 +24,11 @@ contract ChainAdminTest is Test { function setUp() public { owner = makeAddr("random address"); - restriction = new AccessControlRestriction(0, owner); - address[] memory restrictions = new address[](1); - restrictions[0] = address(restriction); - - chainAdmin = new ChainAdmin(restrictions); + chainAdmin = new ChainAdmin(owner, address(0)); gettersFacet = new GettersFacet(); } - function test_getRestrictions() public { - address[] memory restrictions = chainAdmin.getRestrictions(); - assertEq(restrictions[0], address(restriction)); - } - - function test_isRestrictionActive() public { - bool isActive = chainAdmin.isRestrictionActive(address(restriction)); - assertEq(isActive, true); - } - - function test_addRestriction() public { - address[] memory restrictions = chainAdmin.getRestrictions(); - - vm.expectEmit(true, false, false, true); - emit IChainAdmin.RestrictionAdded(owner); - - vm.prank(address(chainAdmin)); - chainAdmin.addRestriction(owner); - } - - function test_addRestrictionRevert() public { - vm.startPrank(address(chainAdmin)); - chainAdmin.addRestriction(owner); - - vm.expectRevert(abi.encodeWithSelector(RestrictionWasAlreadyPresent.selector, owner)); - chainAdmin.addRestriction(owner); - vm.stopPrank(); - } - - function test_removeRestriction() public { - address[] memory restrictions = chainAdmin.getRestrictions(); - - vm.startPrank(address(chainAdmin)); - chainAdmin.addRestriction(owner); - - vm.expectEmit(true, false, false, true); - emit IChainAdmin.RestrictionRemoved(owner); - - chainAdmin.removeRestriction(owner); - vm.stopPrank(); - } - - function test_removeRestrictionRevert() public { - address[] memory restrictions = chainAdmin.getRestrictions(); - - vm.startPrank(address(chainAdmin)); - chainAdmin.addRestriction(owner); - chainAdmin.removeRestriction(owner); - - vm.expectRevert(abi.encodeWithSelector(RestrictionWasNotPresent.selector, owner)); - chainAdmin.removeRestriction(owner); - vm.stopPrank(); - } - function test_setUpgradeTimestamp(uint256 semverMinorVersionMultiplier, uint256 timestamp) public { (major, minor, patch) = gettersFacet.getSemverProtocolVersion(); uint256 protocolVersion = packSemver(major, minor, patch + 1, semverMinorVersionMultiplier); @@ -96,67 +36,43 @@ contract ChainAdminTest is Test { vm.expectEmit(true, false, false, true); emit IChainAdmin.UpdateUpgradeTimestamp(protocolVersion, timestamp); - vm.prank(address(chainAdmin)); + vm.prank(address(owner)); chainAdmin.setUpgradeTimestamp(protocolVersion, timestamp); } function test_multicallRevertNoCalls() public { - Call[] memory calls = new Call[](0); + IChainAdmin.Call[] memory calls = new IChainAdmin.Call[](0); + vm.prank(owner); vm.expectRevert(NoCallsProvided.selector); chainAdmin.multicall(calls, false); } function test_multicallRevertFailedCall() public { - Call[] memory calls = new Call[](1); - calls[0] = Call({target: address(chainAdmin), value: 0, data: abi.encodeCall(gettersFacet.getAdmin, ())}); + IChainAdmin.Call[] memory calls = new IChainAdmin.Call[](1); + calls[0] = IChainAdmin.Call({ + target: address(chainAdmin), + value: 0, + data: abi.encodeCall(gettersFacet.getAdmin, ()) + }); vm.expectRevert(); vm.prank(owner); chainAdmin.multicall(calls, true); } - function test_validateCallAccessToFunctionDenied(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - Call[] memory calls = new Call[](2); - calls[0] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getAdmin, ())}); - calls[1] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getVerifier, ())}); - - vm.prank(owner); - restriction.setRequiredRoleForCall(address(gettersFacet), gettersFacet.getAdmin.selector, role); - - vm.expectRevert( - abi.encodeWithSelector( - AccessToFunctionDenied.selector, - address(gettersFacet), - gettersFacet.getAdmin.selector, - owner - ) - ); - vm.prank(owner); - chainAdmin.multicall(calls, true); - } - - function test_validateCallAccessToFallbackDenied(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - Call[] memory calls = new Call[](2); - calls[0] = Call({target: address(gettersFacet), value: 0, data: ""}); - calls[1] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getVerifier, ())}); - - vm.prank(owner); - restriction.setRequiredRoleForFallback(address(gettersFacet), role); - - vm.expectRevert(abi.encodeWithSelector(AccessToFallbackDenied.selector, address(gettersFacet), owner)); - vm.prank(owner); - chainAdmin.multicall(calls, true); - } - function test_multicall() public { - Call[] memory calls = new Call[](2); - calls[0] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getAdmin, ())}); - calls[1] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getVerifier, ())}); + IChainAdmin.Call[] memory calls = new IChainAdmin.Call[](2); + calls[0] = IChainAdmin.Call({ + target: address(gettersFacet), + value: 0, + data: abi.encodeCall(gettersFacet.getAdmin, ()) + }); + calls[1] = IChainAdmin.Call({ + target: address(gettersFacet), + value: 0, + data: abi.encodeCall(gettersFacet.getVerifier, ()) + }); vm.prank(owner); chainAdmin.multicall(calls, true); diff --git a/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol deleted file mode 100644 index 0e9dc0bce..000000000 --- a/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol +++ /dev/null @@ -1,209 +0,0 @@ -pragma solidity 0.8.24; - -import "openzeppelin-contracts/contracts/utils/Strings.sol"; -import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; -import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; -import {StateTransitionManager} from "contracts/state-transition/StateTransitionManager.sol"; -import {DiamondInit} from "contracts/state-transition/chain-deps/DiamondInit.sol"; -import {PermanentRestriction} from "contracts/governance/PermanentRestriction.sol"; -import {IPermanentRestriction} from "contracts/governance/IPermanentRestriction.sol"; -import {ZeroAddress, ChainZeroAddress, NotAnAdmin, UnallowedImplementation, RemovingPermanentRestriction, CallNotAllowed} from "contracts/common/L1ContractErrors.sol"; -import {Call} from "contracts/governance/Common.sol"; -import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol"; -import {VerifierParams, FeeParams, PubdataPricingMode} from "contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol"; -import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; -import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; -import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; -import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; -import {StateTransitionManagerTest} from "test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol"; - -contract PermanentRestrictionTest is StateTransitionManagerTest { - ChainAdmin internal chainAdmin; - AccessControlRestriction internal restriction; - PermanentRestriction internal permRestriction; - - address internal owner; - address internal hyperchain; - - function setUp() public { - deploy(); - - createNewChainBridgehub(getDiamondCutData(address(diamondInit))); - - vm.stopPrank(); - - owner = makeAddr("owner"); - hyperchain = chainContractAddress.getHyperchain(chainId); - permRestriction = new PermanentRestriction(owner, bridgehub); - restriction = new AccessControlRestriction(0, owner); - address[] memory restrictions = new address[](1); - restrictions[0] = address(restriction); - chainAdmin = new ChainAdmin(restrictions); - } - - function test_ownerAsAddressZero() public { - vm.expectRevert(ZeroAddress.selector); - permRestriction = new PermanentRestriction(address(0), bridgehub); - } - - function test_allowAdminImplementation(bytes32 implementationHash) public { - vm.expectEmit(true, false, false, true); - emit IPermanentRestriction.AdminImplementationAllowed(implementationHash, true); - - vm.prank(owner); - permRestriction.allowAdminImplementation(implementationHash, true); - } - - function test_setAllowedData(bytes memory data) public { - vm.expectEmit(false, false, false, true); - emit IPermanentRestriction.AllowedDataChanged(data, true); - - vm.prank(owner); - permRestriction.setAllowedData(data, true); - } - - function test_setSelectorIsValidated(bytes4 selector) public { - vm.expectEmit(true, false, false, true); - emit IPermanentRestriction.SelectorValidationChanged(selector, true); - - vm.prank(owner); - permRestriction.setSelectorIsValidated(selector, true); - } - - function test_tryCompareAdminOfAChainIsAddressZero() public { - vm.expectRevert(ChainZeroAddress.selector); - permRestriction.tryCompareAdminOfAChain(address(0), owner); - } - - function test_tryCompareAdminOfAChainNotAHyperchain() public { - vm.expectRevert(); - permRestriction.tryCompareAdminOfAChain(makeAddr("random"), owner); - } - - function test_tryCompareAdminOfAChainNotAnAdmin() public { - vm.expectRevert(abi.encodeWithSelector(NotAnAdmin.selector, IZkSyncHyperchain(hyperchain).getAdmin(), owner)); - permRestriction.tryCompareAdminOfAChain(hyperchain, owner); - } - - function test_tryCompareAdminOfAChain() public { - permRestriction.tryCompareAdminOfAChain(hyperchain, newChainAdmin); - } - - function test_validateCallTooShortData() public { - Call memory call = Call({target: hyperchain, value: 0, data: ""}); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCallSetPendingAdminUnallowedImplementation() public { - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.setPendingAdmin.selector, owner) - }); - - vm.expectRevert(abi.encodeWithSelector(UnallowedImplementation.selector, owner.codehash)); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCallSetPendingAdminRemovingPermanentRestriction() public { - vm.prank(owner); - permRestriction.allowAdminImplementation(address(chainAdmin).codehash, true); - - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.setPendingAdmin.selector, address(chainAdmin)) - }); - - vm.expectRevert(RemovingPermanentRestriction.selector); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCallSetPendingAdmin() public { - vm.prank(owner); - permRestriction.allowAdminImplementation(address(chainAdmin).codehash, true); - - vm.prank(address(chainAdmin)); - chainAdmin.addRestriction(address(permRestriction)); - - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.setPendingAdmin.selector, address(chainAdmin)) - }); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCallNotValidatedSelector() public { - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.acceptAdmin.selector) - }); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCallCallNotAllowed() public { - vm.prank(owner); - permRestriction.setSelectorIsValidated(IAdmin.acceptAdmin.selector, true); - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.acceptAdmin.selector) - }); - - vm.expectRevert(abi.encodeWithSelector(CallNotAllowed.selector, call.data)); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCall() public { - vm.prank(owner); - permRestriction.setSelectorIsValidated(IAdmin.acceptAdmin.selector, true); - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.acceptAdmin.selector) - }); - - vm.prank(owner); - permRestriction.setAllowedData(call.data, true); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function createNewChainBridgehub(Diamond.DiamondCutData memory _diamondCut) internal { - vm.stopPrank(); - vm.startPrank(address(0)); - bridgehub.addStateTransitionManager(address(chainContractAddress)); - bridgehub.addToken(baseToken); - bridgehub.setSharedBridge(sharedBridge); - bridgehub.createNewChain({ - _chainId: chainId, - _stateTransitionManager: address(chainContractAddress), - _baseToken: baseToken, - _salt: 0, - _admin: newChainAdmin, - _initData: abi.encode(_diamondCut) - }); - } -} diff --git a/l1-contracts/test/test_config/constant/hardhat.json b/l1-contracts/test/test_config/constant/hardhat.json index 0e63431f0..d73350137 100644 --- a/l1-contracts/test/test_config/constant/hardhat.json +++ b/l1-contracts/test/test_config/constant/hardhat.json @@ -3,96 +3,96 @@ "name": "DAI", "symbol": "DAI", "decimals": 18, - "address": "0xD6E49dd4fb0CA1549566869725d1820aDEb92Ae9" + "address": "0x9F5d1DA449A6c22CCCCE139acD98adD82797fEec" }, { "name": "wBTC", "symbol": "wBTC", "decimals": 8, - "address": "0xcee1f75F30B6908286Cd003C4228A5D9a2851FA4" + "address": "0x275E5aa56a705c8726eE35B3DC6530DE0a0e5f6c" }, { "name": "BAT", "symbol": "BAT", "decimals": 18, - "address": "0x0Bc76A4EfE0748f1697F237fB100741ea6Ceda2d" + "address": "0x18d8b7878Ee8D1cf3c32b177e0B0EC2379084B11" }, { "name": "GNT", "symbol": "GNT", "decimals": 18, - "address": "0x51ae50BcCEE10ac5BEFFA1E4a64106a5f83bc3F8" + "address": "0xe4B41b2c8e3831cbEdC8b3D82047fA30B6B22946" }, { "name": "MLTT", "symbol": "MLTT", "decimals": 18, - "address": "0xa9c7fEEf8586E17D93A05f873BA65f28f48ED259" + "address": "0xe8c976ce9F855825e52015bd1E88Fc84Da1946d2" }, { "name": "DAIK", "symbol": "DAIK", "decimals": 18, - "address": "0x99Efb27598804Aa408A1066550e9d01c45f21b05" + "address": "0xd012f213dDD34858A1357e30B4c491dbFCba8Ee3" }, { "name": "wBTCK", "symbol": "wBTCK", "decimals": 8, - "address": "0x4B701928Da6B3e72775b462A15b8b76ba2d16BbD" + "address": "0x8fbdf8cEAf04E3cc9ac53C90b344c0c2489a0645" }, { "name": "BATK", "symbol": "BATS", "decimals": 18, - "address": "0xf7B03c921dfefB4286b13075BA0335099708368D" + "address": "0x91D6cBBb7006A3fC6686d65375A067624b8D405A" }, { "name": "GNTK", "symbol": "GNTS", "decimals": 18, - "address": "0xc0581Ee28c519533B06cc0aAC1ace98cF63C817b" + "address": "0xEbD3994f1a9d85458bD2a40Fc6927C4048291067" }, { "name": "MLTTK", "symbol": "MLTTS", "decimals": 18, - "address": "0xeB6394F2E8DA607b94dBa2Cf345A965d6D9b3aCD" + "address": "0x194475D0de71858B134e2084fa627B5A7d04334c" }, { "name": "DAIL", "symbol": "DAIL", "decimals": 18, - "address": "0x4311643C5eD7cD0813B4E3Ff5428de71c7d7b8bB" + "address": "0xfB6306147E50e7042E74eA6Cc3db38a8489F8D78" }, { "name": "wBTCL", "symbol": "wBTCP", "decimals": 8, - "address": "0x6b3fbfC9Bb89Ab5F11BE782a1f67c1615c2A5fc3" + "address": "0xA50C21DE8a2d575F915E5f8D6D5ec8eF2935D58e" }, { "name": "BATL", "symbol": "BATW", "decimals": 18, - "address": "0xE003698b7831829843B69D3fB4f9a3133d97b257" + "address": "0xCBaDEF24FA67dB5a56fD84c72b22797A125C3132" }, { "name": "GNTL", "symbol": "GNTW", "decimals": 18, - "address": "0x2417626170675Ccf6022d9db1eFC8f3c59836368" + "address": "0x80C92D6E8d4015660506Cf4F4503eBF3bc073190" }, { "name": "MLTTL", "symbol": "MLTTW", "decimals": 18, - "address": "0x28106C39BE5E51C31D9a289313361D86C9bb7C8E" + "address": "0x44bD975d5735ab2E1b61787228f538e13bF263DC" }, { "name": "Wrapped Ether", "symbol": "WETH", "decimals": 18, - "address": "0x51E83b811930bb4a3aAb3494894ec237Cb6cEc49" + "address": "0xDbEBD56A3068c71f6F71973171c6880a238Ff742" } ] diff --git a/l2-contracts/contracts/dev-contracts/DevL2SharedBridge.sol b/l2-contracts/contracts/dev-contracts/DevL2SharedBridge.sol index e93d5c987..fda1c5932 100644 --- a/l2-contracts/contracts/dev-contracts/DevL2SharedBridge.sol +++ b/l2-contracts/contracts/dev-contracts/DevL2SharedBridge.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.20; import {L2SharedBridge} from "../bridge/L2SharedBridge.sol"; import {L2StandardERC20} from "../bridge/L2StandardERC20.sol"; diff --git a/l2-contracts/contracts/dev-contracts/ITimestampAsserter.sol b/l2-contracts/contracts/dev-contracts/ITimestampAsserter.sol new file mode 100644 index 000000000..47d9ec103 --- /dev/null +++ b/l2-contracts/contracts/dev-contracts/ITimestampAsserter.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +interface ITimestampAsserter { + function assertTimestampInRange(uint256 start, uint256 end) external view; +} diff --git a/l2-contracts/contracts/dev-contracts/Multicall3.sol b/l2-contracts/contracts/dev-contracts/Multicall3.sol new file mode 100644 index 000000000..aaa8b8012 --- /dev/null +++ b/l2-contracts/contracts/dev-contracts/Multicall3.sol @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +/// @title Multicall3 +/// @notice Aggregate results from multiple function calls +/// @dev Multicall & Multicall2 backwards-compatible +/// @dev Aggregate methods are marked `payable` to save 24 gas per call +/// @author Michael Elliot +/// @author Joshua Levine +/// @author Nick Johnson +/// @author Andreas Bigger +/// @author Matt Solomon +contract Multicall3 { + // add this to be excluded from coverage report + function test() internal virtual {} + + struct Call { + address target; + bytes callData; + } + + struct Call3 { + address target; + bool allowFailure; + bytes callData; + } + + struct Call3Value { + address target; + bool allowFailure; + uint256 value; + bytes callData; + } + + struct Result { + bool success; + bytes returnData; + } + + /// @notice Backwards-compatible call aggregation with Multicall + /// @param calls An array of Call structs + /// @return blockNumber The block number where the calls were executed + /// @return returnData An array of bytes containing the responses + function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) { + blockNumber = block.number; + uint256 length = calls.length; + returnData = new bytes[](length); + Call calldata call; + for (uint256 i = 0; i < length; ) { + bool success; + call = calls[i]; + (success, returnData[i]) = call.target.call(call.callData); + require(success, "Multicall3: call failed"); + unchecked { + ++i; + } + } + } + + /// @notice Backwards-compatible with Multicall2 + /// @notice Aggregate calls without requiring success + /// @param requireSuccess If true, require all calls to succeed + /// @param calls An array of Call structs + /// @return returnData An array of Result structs + function tryAggregate( + bool requireSuccess, + Call[] calldata calls + ) public payable returns (Result[] memory returnData) { + uint256 length = calls.length; + returnData = new Result[](length); + Call calldata call; + for (uint256 i = 0; i < length; ) { + Result memory result = returnData[i]; + call = calls[i]; + (result.success, result.returnData) = call.target.call(call.callData); + if (requireSuccess) require(result.success, "Multicall3: call failed"); + unchecked { + ++i; + } + } + } + + /// @notice Backwards-compatible with Multicall2 + /// @notice Aggregate calls and allow failures using tryAggregate + /// @param calls An array of Call structs + /// @return blockNumber The block number where the calls were executed + /// @return blockHash The hash of the block where the calls were executed + /// @return returnData An array of Result structs + function tryBlockAndAggregate( + bool requireSuccess, + Call[] calldata calls + ) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { + blockNumber = block.number; + blockHash = blockhash(block.number); + returnData = tryAggregate(requireSuccess, calls); + } + + /// @notice Backwards-compatible with Multicall2 + /// @notice Aggregate calls and allow failures using tryAggregate + /// @param calls An array of Call structs + /// @return blockNumber The block number where the calls were executed + /// @return blockHash The hash of the block where the calls were executed + /// @return returnData An array of Result structs + function blockAndAggregate( + Call[] calldata calls + ) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { + (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls); + } + + /// @notice Aggregate calls, ensuring each returns success if required + /// @param calls An array of Call3 structs + /// @return returnData An array of Result structs + function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) { + uint256 length = calls.length; + returnData = new Result[](length); + Call3 calldata calli; + for (uint256 i = 0; i < length; ) { + Result memory result = returnData[i]; + calli = calls[i]; + (result.success, result.returnData) = calli.target.call(calli.callData); + assembly { + // Revert if the call fails and failure is not allowed + // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` + if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { + // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) + mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) + // set data offset + mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) + // set length of revert string + mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) + // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) + mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) + revert(0x00, 0x64) + } + } + unchecked { + ++i; + } + } + } + + /// @notice Aggregate calls with a msg value + /// @notice Reverts if msg.value is less than the sum of the call values + /// @param calls An array of Call3Value structs + /// @return returnData An array of Result structs + function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) { + uint256 valAccumulator; + uint256 length = calls.length; + returnData = new Result[](length); + Call3Value calldata calli; + for (uint256 i = 0; i < length; ) { + Result memory result = returnData[i]; + calli = calls[i]; + uint256 val = calli.value; + // Humanity will be a Type V Kardashev Civilization before this overflows - andreas + // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256 + unchecked { + valAccumulator += val; + } + (result.success, result.returnData) = calli.target.call{value: val}(calli.callData); + assembly { + // Revert if the call fails and failure is not allowed + // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` + if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { + // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) + mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) + // set data offset + mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) + // set length of revert string + mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) + // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) + mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) + revert(0x00, 0x84) + } + } + unchecked { + ++i; + } + } + // Finally, make sure the msg.value = SUM(call[0...i].value) + require(msg.value == valAccumulator, "Multicall3: value mismatch"); + } + + /// @notice Returns the block hash for the given block number + /// @param blockNumber The block number + function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) { + blockHash = blockhash(blockNumber); + } + + /// @notice Returns the block number + function getBlockNumber() public view returns (uint256 blockNumber) { + blockNumber = block.number; + } + + /// @notice Returns the block coinbase + function getCurrentBlockCoinbase() public view returns (address coinbase) { + coinbase = block.coinbase; + } + + /// @notice Returns the block difficulty + function getCurrentBlockDifficulty() public view returns (uint256 difficulty) { + difficulty = block.prevrandao; + } + + /// @notice Returns the block gas limit + function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) { + gaslimit = block.gaslimit; + } + + /// @notice Returns the block timestamp + function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { + timestamp = block.timestamp; + } + + /// @notice Returns the (ETH) balance of a given address + function getEthBalance(address addr) public view returns (uint256 balance) { + balance = addr.balance; + } + + /// @notice Returns the block hash of the last block + function getLastBlockHash() public view returns (bytes32 blockHash) { + unchecked { + blockHash = blockhash(block.number - 1); + } + } + + /// @notice Gets the base fee of the given block + /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain + function getBasefee() public view returns (uint256 basefee) { + basefee = block.basefee; + } + + /// @notice Returns the chain id + function getChainId() public view returns (uint256 chainid) { + chainid = block.chainid; + } +} diff --git a/l2-contracts/contracts/dev-contracts/TimestampAsserter.sol b/l2-contracts/contracts/dev-contracts/TimestampAsserter.sol new file mode 100644 index 000000000..445313fe0 --- /dev/null +++ b/l2-contracts/contracts/dev-contracts/TimestampAsserter.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ITimestampAsserter} from "./ITimestampAsserter.sol"; + +error TimestampOutOfRange(uint256 currentTimestamp, uint256 start, uint256 end); + +/// @title TimestampAsserter +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +/// @dev A contract that verifies if the current block timestamp falls within a specified range. +/// This is useful for custom account abstraction where time-bound checks are needed but accessing block.timestamp +/// directly is not possible. +contract TimestampAsserter is ITimestampAsserter { + function assertTimestampInRange(uint256 _start, uint256 _end) external view { + if (block.timestamp < _start || block.timestamp > _end) { + revert TimestampOutOfRange(block.timestamp, _start, _end); + } + } +} diff --git a/l2-contracts/foundry.toml b/l2-contracts/foundry.toml index deb178a12..7fb4971c7 100644 --- a/l2-contracts/foundry.toml +++ b/l2-contracts/foundry.toml @@ -10,4 +10,4 @@ remappings = [ ] [profile.default.zksync] -zksolc = "1.5.0" +zksolc = "1.5.6" diff --git a/system-contracts/foundry.toml b/system-contracts/foundry.toml index 312de073f..4f5780943 100644 --- a/system-contracts/foundry.toml +++ b/system-contracts/foundry.toml @@ -11,4 +11,5 @@ remappings = [ [profile.default.zksync] zksolc = "1.5.6" +enable_eravm_extensions = true suppressed_errors = ["sendtransfer"] diff --git a/system-contracts/scripts/calculate-hashes.ts b/system-contracts/scripts/calculate-hashes.ts index e63c3abf8..71c5a8d71 100644 --- a/system-contracts/scripts/calculate-hashes.ts +++ b/system-contracts/scripts/calculate-hashes.ts @@ -42,10 +42,10 @@ const findFilesEndingWith = (path: string, endingWith: string): string[] => { } }; -const SOLIDITY_ARTIFACTS_DIR = "artifacts-zk"; +const SOLIDITY_ARTIFACTS_DIR = "zkout"; const getSolidityContractDetails = (dir: string, contractName: string): ContractDetails => { - const bytecodePath = join(SOLIDITY_ARTIFACTS_DIR, dir, contractName + ".sol", contractName + ".json"); + const bytecodePath = join(SOLIDITY_ARTIFACTS_DIR, contractName + ".sol", contractName + ".json"); const sourceCodePath = join(dir, contractName + ".sol"); return { contractName, @@ -55,7 +55,7 @@ const getSolidityContractDetails = (dir: string, contractName: string): Contract }; const getSolidityContractsDetails = (dir: string): ContractDetails[] => { - const bytecodesDir = join(SOLIDITY_ARTIFACTS_DIR, dir); + const bytecodesDir = SOLIDITY_ARTIFACTS_DIR; const dirsEndingWithSol = findDirsEndingWith(bytecodesDir, ".sol"); const contractNames = dirsEndingWithSol.map((d) => d.replace(".sol", "")); const solidityContractsDetails = contractNames.map((c) => getSolidityContractDetails(dir, c)); @@ -100,7 +100,7 @@ const readBytecode = (details: ContractDetails): string => { try { if (details.bytecodePath.endsWith(".json")) { const jsonFile = fs.readFileSync(absolutePath, "utf8"); - return ethers.utils.hexlify(JSON.parse(jsonFile).bytecode); + return ethers.utils.hexlify("0x" + JSON.parse(jsonFile).bytecode.object); } else { return ethers.utils.hexlify(fs.readFileSync(absolutePath).toString(), { allowMissingPrefix: true }); } diff --git a/system-contracts/scripts/preprocess-bootloader.ts b/system-contracts/scripts/preprocess-bootloader.ts index 952181455..e3dc18aaf 100644 --- a/system-contracts/scripts/preprocess-bootloader.ts +++ b/system-contracts/scripts/preprocess-bootloader.ts @@ -13,7 +13,8 @@ const preprocess = require("preprocess"); const SYSTEM_PARAMS = require("../../SystemConfig.json"); /* eslint-enable@typescript-eslint/no-var-requires */ -const OUTPUT_DIR = "bootloader/build"; +const OUTPUT_DIR_1 = "contracts-preprocessed/bootloader"; +const OUTPUT_DIR_2 = "bootloader/build"; const PREPROCCESING_MODES = ["proved_batch", "playground_batch"]; @@ -224,15 +225,32 @@ async function main() { }); const provedBootloaderWithTests = preprocess.preprocess(bootloaderWithTests, { BOOTLOADER_TYPE: "proved_batch" }); - if (!existsSync(OUTPUT_DIR)) { - mkdirSync(OUTPUT_DIR); + if (!existsSync(OUTPUT_DIR_1)) { + mkdirSync(OUTPUT_DIR_1); } - writeFileSync(`${OUTPUT_DIR}/bootloader_test.yul`, provedBootloaderWithTests); - writeFileSync(`${OUTPUT_DIR}/proved_batch.yul`, provedBatchBootloader); - writeFileSync(`${OUTPUT_DIR}/playground_batch.yul`, playgroundBatchBootloader); - writeFileSync(`${OUTPUT_DIR}/gas_test.yul`, gasTestBootloader); - writeFileSync(`${OUTPUT_DIR}/fee_estimate.yul`, feeEstimationBootloader); + if (!existsSync(OUTPUT_DIR_2)) { + mkdirSync(OUTPUT_DIR_2); + } + + const transferTest = readFileSync("bootloader/tests/transfer_test.yul").toString(); + const dummy = readFileSync("bootloader/tests/dummy.yul").toString(); + + writeFileSync(`${OUTPUT_DIR_1}/bootloader_test.yul`, provedBootloaderWithTests); + writeFileSync(`${OUTPUT_DIR_1}/proved_batch.yul`, provedBatchBootloader); + writeFileSync(`${OUTPUT_DIR_1}/playground_batch.yul`, playgroundBatchBootloader); + writeFileSync(`${OUTPUT_DIR_1}/gas_test.yul`, gasTestBootloader); + writeFileSync(`${OUTPUT_DIR_1}/fee_estimate.yul`, feeEstimationBootloader); + writeFileSync(`${OUTPUT_DIR_1}/dummy.yul`, dummy); + writeFileSync(`${OUTPUT_DIR_1}/transfer_test.yul`, transferTest); + + writeFileSync(`${OUTPUT_DIR_2}/bootloader_test.yul`, provedBootloaderWithTests); + writeFileSync(`${OUTPUT_DIR_2}/proved_batch.yul`, provedBatchBootloader); + writeFileSync(`${OUTPUT_DIR_2}/playground_batch.yul`, playgroundBatchBootloader); + writeFileSync(`${OUTPUT_DIR_2}/gas_test.yul`, gasTestBootloader); + writeFileSync(`${OUTPUT_DIR_2}/fee_estimate.yul`, feeEstimationBootloader); + writeFileSync(`${OUTPUT_DIR_2}/dummy.yul`, dummy); + writeFileSync(`${OUTPUT_DIR_2}/transfer_test.yul`, transferTest); console.log("Bootloader preprocessing done!"); } From a3ccf98fc1d864b716f02876e579a2a94539d39e Mon Sep 17 00:00:00 2001 From: Thomas Nguy <81727899+thomas-nguy@users.noreply.github.com> Date: Tue, 19 Nov 2024 22:37:07 +0900 Subject: [PATCH 138/183] feat(system-contracts): remove unecessary methods from L2BaseToken.sol (#509) Co-authored-by: Zach Kolodny --- system-contracts/SystemContractsHashes.json | 32 +++++++++---------- system-contracts/contracts/L2BaseToken.sol | 18 ----------- .../contracts/interfaces/IBaseToken.sol | 6 ---- system-contracts/test/L2BaseToken.spec.ts | 21 ------------ 4 files changed, 16 insertions(+), 61 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 8eeff8ac5..96e1d2cf7 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": "0x01000059c988dac86a1fe9ff2d929f118eaf640d2c073a7e089f33cda3183784", + "bytecodeHash": "0x01000059e8dff1f7b5f2d89b85e5dd0f8af0c6a6c40cf0e4e5dd525bb4576e77", "sourceCodeHash": "0x2e0e09d57a04bd1e722d8bf8c6423fdf3f8bca44e5e8c4f6684f987794be066e" }, { "contractName": "BootloaderUtilities", "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006dfcc723139e24b127181ad5cec6c4b57935c944548ad2e7b65505bdedd", + "bytecodeHash": "0x010006df421c055eac170f590f52ab7f43e22c513dd724b4b1c939f5842ccf02", "sourceCodeHash": "0x0f1213c4b95acb71f4ab5d4082cc1aeb2bd5017e1cccd46afc66e53268609d85" }, { "contractName": "ComplexUpgrader", "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x01000047171b9f2496e91fedc2a691b926d67c664718e09e7741abb936356ce8", + "bytecodeHash": "0x010000478fa72dac9eff50e0cce3b200f11a506d4649eb621b100b1d7afe5b9d", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013f5629aea4f024a0391184de582368e27eb00fd4e4f04d38285127e04f", + "bytecodeHash": "0x0100013fe9cacee0324f0b7de2e94a65a4c87b782514723075d835687da36bd6", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x0100042db9e3c6a96189306802a818ad22ceac9beb9750d184a17be348efc5b9", + "bytecodeHash": "0x0100042d3c6d16ebea6d0cb473965f18f45f09d0f71b15fada97e606eab65a06", "sourceCodeHash": "0x82f81fbf5fb007a9cac97462d50907ca5d7a1af62d82d2645e093ed8647a5209" }, { "contractName": "Create2Factory", "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003f67bf604cec81253c6d5876dfc05255da12ad83ee32f56a2e3233fb8f", + "bytecodeHash": "0x0100003fed8b9742c17b0d2a287f4bc7d6e080fbad4236ab9ad52fdf4a8e892a", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x010004dbb7b5d17f1013d67de0409a8fa3bc84af9226b5c759b9a0a1d0a2e8dc", + "bytecodeHash": "0x010004db0973d6635333d6cd2132a2d99044c5e2077135e9e2a360620d3926e0", "sourceCodeHash": "0xebffe840ebbd9329edb1ebff8ca50f6935e7dabcc67194a896fcc2e968d46dfb" }, { @@ -59,56 +59,56 @@ "contractName": "ImmutableSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033962f4c689f265e804df8ae9ab06f1ab8d044e72385e41bcd411d04a2", + "bytecodeHash": "0x010000336f093aca5141fd8924f3d15ed85c23c0e9c94850155d7d75787750a5", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x0100006916feb836433c433d6e82f97fb159fe1feb3dd2523de09b23a2335a79", + "bytecodeHash": "0x010000696c0f2f9698c9a8aca059305df822a62d2cdd58145c8b94381c262ddc", "sourceCodeHash": "0xb39b5b81168653e0c5062f7b8e1d6d15a4e186df3317f192f0cb2fc3a74f5448" }, { "contractName": "L1Messenger", "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010002619d1a0168c99f201cac7ff8b787f1975e1dd6aaf6baba68aade3d3c52", + "bytecodeHash": "0x01000261e4a17d750009866862df7d1f6400752ce204fc489cdefd95089efca2", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f3b310a8c54b771dc7ee43e1f6da2efa3a2b470c511a3039c130cd63cb", - "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" + "bytecodeHash": "0x010000db7dbc0d4e3577a4866dd39d96d79f34070ee9c9aa1b3c182bc7204070", + "sourceCodeHash": "0xdea518b1ea16718b0f0ec6155b227a8bc8f51374a9eebf7bc17cfe84433df740" }, { "contractName": "MsgValueSimulator", "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005983e6e523fc73e5326d31e0e96fa440fec2818e923fe57a48688617aa", + "bytecodeHash": "0x010000590dbb07ab08067502a8668b91ca1d71cc79c66c571f3e8324d835b38b", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cfd785169945521d4d3bece055ed7c88b79eabdc7bda73f62583bd844c", + "bytecodeHash": "0x010000cf4013a7b83219b99fc665d1f22b579ef2d36f3928d6ee06e1be0862e0", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x010000411cea63a93f499cb4b434c13c9c0300126fe1c2714e1755c10889072c", + "bytecodeHash": "0x01000041ac82adc2e9de2e330918e70ac94fdf151f173c7bfff59170d6b90812", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a5d85e6baddaf82e2d7a43974ab3ad285facf4c3e28844adfc0125a0ce", + "bytecodeHash": "0x010001a58ea92274152ff90546a630bd47ed923131fa1d3469bd12689009760d", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { diff --git a/system-contracts/contracts/L2BaseToken.sol b/system-contracts/contracts/L2BaseToken.sol index 9f826a80b..d7a047a8f 100644 --- a/system-contracts/contracts/L2BaseToken.sol +++ b/system-contracts/contracts/L2BaseToken.sol @@ -127,22 +127,4 @@ contract L2BaseToken is IBaseToken, SystemContractBase { // solhint-disable-next-line func-named-parameters return abi.encodePacked(IMailbox.finalizeEthWithdrawal.selector, _to, _amount, _sender, _additionalData); } - - /// @dev This method has not been stabilized and might be - /// removed later on. - function name() external pure override returns (string memory) { - return "Ether"; - } - - /// @dev This method has not been stabilized and might be - /// removed later on. - function symbol() external pure override returns (string memory) { - return "ETH"; - } - - /// @dev This method has not been stabilized and might be - /// removed later on. - function decimals() external pure override returns (uint8) { - return 18; - } } diff --git a/system-contracts/contracts/interfaces/IBaseToken.sol b/system-contracts/contracts/interfaces/IBaseToken.sol index fc32c7b83..2bd15be51 100644 --- a/system-contracts/contracts/interfaces/IBaseToken.sol +++ b/system-contracts/contracts/interfaces/IBaseToken.sol @@ -9,12 +9,6 @@ interface IBaseToken { function totalSupply() external view returns (uint256); - function name() external pure returns (string memory); - - function symbol() external pure returns (string memory); - - function decimals() external pure returns (uint8); - function mint(address _account, uint256 _amount) external; function withdraw(address _l1Receiver) external payable; diff --git a/system-contracts/test/L2BaseToken.spec.ts b/system-contracts/test/L2BaseToken.spec.ts index d73f0444d..f4d9c5c92 100644 --- a/system-contracts/test/L2BaseToken.spec.ts +++ b/system-contracts/test/L2BaseToken.spec.ts @@ -146,27 +146,6 @@ describe("L2BaseToken tests", () => { }); }); - describe("name", () => { - it("correct name", async () => { - const name = await L2BaseToken.name(); - expect(name).to.equal("Ether"); - }); - }); - - describe("symbol", () => { - it("correct symbol", async () => { - const symbol = await L2BaseToken.symbol(); - expect(symbol).to.equal("ETH"); - }); - }); - - describe("decimals", () => { - it("correct decimals", async () => { - const decimals = await L2BaseToken.decimals(); - expect(decimals).to.equal(18); - }); - }); - describe("withdraw", () => { it("event, balance, totalsupply", async () => { const amountToWithdraw: BigNumber = ethers.utils.parseEther("1.0"); From f8b2651eb148a5b378b157c99736e5d0c7434ec4 Mon Sep 17 00:00:00 2001 From: koloz193 Date: Wed, 20 Nov 2024 19:09:10 +0700 Subject: [PATCH 139/183] readd hash check (#1074) --- .github/workflows/system-contracts-ci.yaml | 34 ++++++ system-contracts/SystemContractsHashes.json | 106 +++++++++++-------- system-contracts/package.json | 2 +- system-contracts/scripts/calculate-hashes.ts | 12 ++- 4 files changed, 104 insertions(+), 50 deletions(-) diff --git a/.github/workflows/system-contracts-ci.yaml b/.github/workflows/system-contracts-ci.yaml index cf6b984c0..018a556e4 100644 --- a/.github/workflows/system-contracts-ci.yaml +++ b/.github/workflows/system-contracts-ci.yaml @@ -143,3 +143,37 @@ jobs: - name: Print output logs of era_test_node if: always() run: cat era_test_node.log + + check-hashes: + needs: [build] + runs-on: ubuntu-latest + + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.18.0 + cache: yarn + + - name: Install dependencies + run: yarn + + - name: Restore artifacts cache + uses: actions/cache/restore@v3 + with: + fail-on-cache-miss: true + key: artifacts-system-${{ github.sha }} + path: | + system-contracts/zkout + system-contracts/cache-forge + system-contracts/bootloader/build + system-contracts/artifacts-zk + system-contracts/cache-zk + system-contracts/typechain + system-contracts/contracts-preprocessed + + - name: Check hashes + run: yarn sc calculate-hashes:check diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 96e1d2cf7..3404828fe 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -1,212 +1,226 @@ [ { "contractName": "AccountCodeStorage", - "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", + "bytecodePath": "zkout/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x01000059e8dff1f7b5f2d89b85e5dd0f8af0c6a6c40cf0e4e5dd525bb4576e77", + "bytecodeHash": "0x01000059e58c4b510c6d3000e492d1c98cf6f5e97b17485d2fd4ae20774bbe31", "sourceCodeHash": "0x2e0e09d57a04bd1e722d8bf8c6423fdf3f8bca44e5e8c4f6684f987794be066e" }, { "contractName": "BootloaderUtilities", - "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", + "bytecodePath": "zkout/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006df421c055eac170f590f52ab7f43e22c513dd724b4b1c939f5842ccf02", + "bytecodeHash": "0x010006dff879b6fda1310d6f6bacb5188744476796e0e78b8ef0f3665d221f64", "sourceCodeHash": "0x0f1213c4b95acb71f4ab5d4082cc1aeb2bd5017e1cccd46afc66e53268609d85" }, { "contractName": "ComplexUpgrader", - "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", + "bytecodePath": "zkout/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x010000478fa72dac9eff50e0cce3b200f11a506d4649eb621b100b1d7afe5b9d", + "bytecodeHash": "0x010000477573dcfd9cf37d44859d54b7b176acba85ae8f18fd5ace0308d6f0ec", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", - "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", + "bytecodePath": "zkout/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013fe9cacee0324f0b7de2e94a65a4c87b782514723075d835687da36bd6", + "bytecodeHash": "0x0100013f2d65426f271606752ad9ece505c728b90377406aa46cef48e611fa1f", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", - "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", + "bytecodePath": "zkout/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x0100042d3c6d16ebea6d0cb473965f18f45f09d0f71b15fada97e606eab65a06", + "bytecodeHash": "0x0100042d3e0b1d7027c7095a48fbac09515ee2417407678e237c0d29a4fbf7c2", "sourceCodeHash": "0x82f81fbf5fb007a9cac97462d50907ca5d7a1af62d82d2645e093ed8647a5209" }, { "contractName": "Create2Factory", - "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", + "bytecodePath": "zkout/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003fed8b9742c17b0d2a287f4bc7d6e080fbad4236ab9ad52fdf4a8e892a", + "bytecodeHash": "0x0100003f1e5d0e280c87a85625b19e23840538c0fee2adb6f473ae7deda99666", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", - "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", + "bytecodePath": "zkout/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x010004db0973d6635333d6cd2132a2d99044c5e2077135e9e2a360620d3926e0", + "bytecodeHash": "0x010004dbe4df43333285d1984685bdb9aec3044931473c777483d63a99e66bb9", "sourceCodeHash": "0xebffe840ebbd9329edb1ebff8ca50f6935e7dabcc67194a896fcc2e968d46dfb" }, { "contractName": "EmptyContract", - "bytecodePath": "artifacts-zk/contracts-preprocessed/EmptyContract.sol/EmptyContract.json", + "bytecodePath": "zkout/EmptyContract.sol/EmptyContract.json", "sourceCodePath": "contracts-preprocessed/EmptyContract.sol", - "bytecodeHash": "0x01000007947dfd1aab45b52e5998b442bfbd4d565af494fb8082a810c6ed0b50", + "bytecodeHash": "0x0100000759fbd07e0d0781d79416d24706955ba013862ffdd9c45d429d474784", "sourceCodeHash": "0xcac36c5afafbcff83601f4fbfdff660aa66d8c80ed97b9322d3011c1926b554d" }, { "contractName": "ImmutableSimulator", - "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", + "bytecodePath": "zkout/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x010000336f093aca5141fd8924f3d15ed85c23c0e9c94850155d7d75787750a5", + "bytecodeHash": "0x01000035b6bcb201f45b122be5632b55de78374a18efb2b812c943c3ee9ad154", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", - "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", + "bytecodePath": "zkout/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000696c0f2f9698c9a8aca059305df822a62d2cdd58145c8b94381c262ddc", + "bytecodeHash": "0x010000692d7c6660a194c9128f937fcf638a3309424fa90d8e25107b76928d40", "sourceCodeHash": "0xb39b5b81168653e0c5062f7b8e1d6d15a4e186df3317f192f0cb2fc3a74f5448" }, { "contractName": "L1Messenger", - "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", + "bytecodePath": "zkout/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000261e4a17d750009866862df7d1f6400752ce204fc489cdefd95089efca2", + "bytecodeHash": "0x01000261fc2f8bc373116ad7adab8fe9022996cf866f4eecf81034a7ad2ef357", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", - "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", + "bytecodePath": "zkout/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000db7dbc0d4e3577a4866dd39d96d79f34070ee9c9aa1b3c182bc7204070", + "bytecodeHash": "0x010000ddd98f7915c8d5f04c9011f301b9714b10cd3c9d30f89d93c29d3dd3a7", "sourceCodeHash": "0xdea518b1ea16718b0f0ec6155b227a8bc8f51374a9eebf7bc17cfe84433df740" }, { "contractName": "MsgValueSimulator", - "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", + "bytecodePath": "zkout/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x010000590dbb07ab08067502a8668b91ca1d71cc79c66c571f3e8324d835b38b", + "bytecodeHash": "0x0100005990ed517bc98ec25743f96de6d45efccce22b32a81093a10ba2e0eab5", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", - "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", + "bytecodePath": "zkout/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cf4013a7b83219b99fc665d1f22b579ef2d36f3928d6ee06e1be0862e0", + "bytecodeHash": "0x010000d1e115f2aef2379c5544d8484268e305a60871d658b7af0be1870d3ac0", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", - "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", + "bytecodePath": "zkout/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041ac82adc2e9de2e330918e70ac94fdf151f173c7bfff59170d6b90812", + "bytecodeHash": "0x01000041bfabdaaca186f9dc45a63b51be68d169c295b738788bc26f59370281", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", - "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", + "bytecodePath": "zkout/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a58ea92274152ff90546a630bd47ed923131fa1d3469bd12689009760d", + "bytecodeHash": "0x010001a5ede6eafde755e1630fd4b287ad382955fa0339cb1f0bef5d35f858a7", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { "contractName": "EventWriter", - "bytecodePath": "contracts-preprocessed/artifacts/EventWriter.yul/EventWriter.yul.zbin", + "bytecodePath": "zkout/EventWriter.yul/contracts-preprocessed/EventWriter.yul.json", "sourceCodePath": "contracts-preprocessed/EventWriter.yul", "bytecodeHash": "0x0100001739ee6f13091800b6cac4bd0c2c81dd81b449b6ddf3e663ce098c60ad", "sourceCodeHash": "0xfcf4828bcc109dea5f88c38f428d9ac5e18d5a2767fa4909277802c7e38c1f93" }, { "contractName": "CodeOracle", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/CodeOracle.yul/CodeOracle.yul.zbin", + "bytecodePath": "zkout/CodeOracle.yul/contracts-preprocessed/precompiles/CodeOracle.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/CodeOracle.yul", "bytecodeHash": "0x010000210cd0b1ab22d71e01091a15cb8190e30d884784b092640d83aaf6c462", "sourceCodeHash": "0x476063e7907f2b7a532c4da6f606fa07186b5a10d77af8fdd83dbea3d9f23f93" }, { "contractName": "EcAdd", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcAdd.yul/EcAdd.yul.zbin", + "bytecodePath": "zkout/EcAdd.yul/contracts-preprocessed/precompiles/EcAdd.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/EcAdd.yul", "bytecodeHash": "0x01000085f63553694e753270541123b5e2c2b809f1b883db3ceb830366524a40", "sourceCodeHash": "0xdfec1c5f8c6a93df1c8821f1ac15058a18a640bcbdeb67dc4a017f2153ff1c86" }, { "contractName": "EcMul", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcMul.yul/EcMul.yul.zbin", + "bytecodePath": "zkout/EcMul.yul/contracts-preprocessed/precompiles/EcMul.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/EcMul.yul", "bytecodeHash": "0x010000bbf677d3be4dbbf5dad75e63e87f2b1baf1b457d2507cb58025e26a2bf", "sourceCodeHash": "0x0e3f320c8a9532425b85809bf0a2136e707046a01bf20491ec03c77887516c43" }, { "contractName": "EcPairing", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcPairing.yul/EcPairing.yul.zbin", + "bytecodePath": "zkout/EcPairing.yul/contracts-preprocessed/precompiles/EcPairing.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/EcPairing.yul", "bytecodeHash": "0x01000ef38d94382bae33b3ffc36660e56b2df54c49c32963f49153830c36121e", "sourceCodeHash": "0x5d008cedc44e0e52c2567fd2b877916b2ec5e7c80294cf99b66485e50a6f2c12" }, { "contractName": "Ecrecover", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Ecrecover.yul/Ecrecover.yul.zbin", + "bytecodePath": "zkout/Ecrecover.yul/contracts-preprocessed/precompiles/Ecrecover.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/Ecrecover.yul", "bytecodeHash": "0x01000013ffc212bb76a7b9108abff6be1d0746154e36d32e9c69268ef95e556a", "sourceCodeHash": "0x21e03ab7a5f518a21258669c82506b1d4d1141f8fd4f30bb385f9730580ddd3c" }, { "contractName": "Keccak256", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Keccak256.yul/Keccak256.yul.zbin", + "bytecodePath": "zkout/Keccak256.yul/contracts-preprocessed/precompiles/Keccak256.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/Keccak256.yul", "bytecodeHash": "0x0100000f16ef9261284d26f08a560cd482ff7eb7944fe37ac99113aa4eb75188", "sourceCodeHash": "0xb454e7760732ce1fffc75174c8cf54dca422206cf1e52a29d274b310b574f26d" }, { "contractName": "P256Verify", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/P256Verify.yul/P256Verify.yul.zbin", + "bytecodePath": "zkout/P256Verify.yul/contracts-preprocessed/precompiles/P256Verify.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/P256Verify.yul", "bytecodeHash": "0x0100000ff914846f07b729f21be741f039c13d9c8e7c53e4db3a4c9a9f7e022d", "sourceCodeHash": "0x976b68d0362307313fd1aaea309eaa2d849187f37da451618c70dd3a6ac3cf3c" }, { "contractName": "SHA256", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/SHA256.yul/SHA256.yul.zbin", + "bytecodePath": "zkout/SHA256.yul/contracts-preprocessed/precompiles/SHA256.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/SHA256.yul", "bytecodeHash": "0x01000017cac2faad1aa8a1fd865fa464fbf092dbd8031dedb52fa6b8632e5b97", "sourceCodeHash": "0xfd4290467e26e992f39db9ca132e78ce99ce042b0254a368f1d7832dc94ddefb" }, { "contractName": "bootloader_test", - "bytecodePath": "bootloader/build/artifacts/bootloader_test.yul/bootloader_test.yul.zbin", + "bytecodePath": "zkout/bootloader_test.yul/contracts-preprocessed/bootloader/bootloader_test.yul.json", "sourceCodePath": "bootloader/build/bootloader_test.yul", "bytecodeHash": "0x010003ade02adac2c039832861a6649c6cbb7abbb2ff8542c6aefff7bde06a9c", "sourceCodeHash": "0x006fdf461899dec5fdb34301c23e6819eb93e275907cbfc67d73fccfb47cae68" }, + { + "contractName": "dummy", + "bytecodePath": "zkout/dummy.yul/contracts-preprocessed/bootloader/dummy.yul.json", + "sourceCodePath": "bootloader/build/dummy.yul", + "bytecodeHash": "0x01000007b6aafb589f3b3d53466cb263cb237e75169fba7ba728aba0134007f9", + "sourceCodeHash": "0xfac5ca11a9882425af93fe5bac6d10055b119cf13af79e6a2f4e74e8411b9c85" + }, { "contractName": "fee_estimate", - "bytecodePath": "bootloader/build/artifacts/fee_estimate.yul/fee_estimate.yul.zbin", + "bytecodePath": "zkout/fee_estimate.yul/contracts-preprocessed/bootloader/fee_estimate.yul.json", "sourceCodePath": "bootloader/build/fee_estimate.yul", "bytecodeHash": "0x01000905327a3aeb212816e7e0f6c16c5acc491c714c06d823c4bbc7075b62d6", "sourceCodeHash": "0x8a858319bac2924a3dee778218a7fe5e23898db0d87b02d7b783f94c5a02d257" }, { "contractName": "gas_test", - "bytecodePath": "bootloader/build/artifacts/gas_test.yul/gas_test.yul.zbin", + "bytecodePath": "zkout/gas_test.yul/contracts-preprocessed/bootloader/gas_test.yul.json", "sourceCodePath": "bootloader/build/gas_test.yul", "bytecodeHash": "0x01000871cdb46e23c5b65176cd772e368d255c80290058b89e9644efbe8d7c53", "sourceCodeHash": "0x89f5ad470f10e755fa57b82507518e571c24409a328bc33aeba26e9518ad1c3e" }, { "contractName": "playground_batch", - "bytecodePath": "bootloader/build/artifacts/playground_batch.yul/playground_batch.yul.zbin", + "bytecodePath": "zkout/playground_batch.yul/contracts-preprocessed/bootloader/playground_batch.yul.json", "sourceCodePath": "bootloader/build/playground_batch.yul", "bytecodeHash": "0x01000909408f87054598e7a1e9fbc58e0e9733b0ab5030618eef36ef746cac68", "sourceCodeHash": "0x769448c4fd2b65c43d758ca5f34dd29d9b9dd3000fd0ec89cffcaf8d365a64fd" }, { "contractName": "proved_batch", - "bytecodePath": "bootloader/build/artifacts/proved_batch.yul/proved_batch.yul.zbin", + "bytecodePath": "zkout/proved_batch.yul/contracts-preprocessed/bootloader/proved_batch.yul.json", "sourceCodePath": "bootloader/build/proved_batch.yul", "bytecodeHash": "0x01000881f046342b70470a7e81423b5903dfe06669d01292e7dc6f8eb73bf404", "sourceCodeHash": "0x908bc6ddb34ef89b125e9637239a1149deacacd91255781d82a65a542a39036e" + }, + { + "contractName": "transfer_test", + "bytecodePath": "zkout/transfer_test.yul/contracts-preprocessed/bootloader/transfer_test.yul.json", + "sourceCodePath": "bootloader/build/transfer_test.yul", + "bytecodeHash": "0x0100001532ccf5b061252699f6d2c677d987c775f48152271d5be4f02e41e454", + "sourceCodeHash": "0xb828600c6f7366971580b68da39c3e449b9a0f922f52dd9841f33ae7f51ee71c" } ] diff --git a/system-contracts/package.json b/system-contracts/package.json index cf6d474ca..8e29a46ab 100644 --- a/system-contracts/package.json +++ b/system-contracts/package.json @@ -50,7 +50,7 @@ ] }, "scripts": { - "build": "yarn build:system-contracts && yarn build:bootloader", + "build": "yarn build:system-contracts && yarn build:bootloader && forge build --zksync", "build:bootloader": "yarn preprocess:bootloader && yarn compile-yul compile-bootloader", "build:system-contracts": "yarn preprocess:system-contracts && hardhat compile && yarn compile-yul compile-precompiles", "build:test-system-contracts": "yarn preprocess:system-contracts --test-mode && hardhat compile && yarn compile-yul compile-precompiles && yarn compile-zasm", diff --git a/system-contracts/scripts/calculate-hashes.ts b/system-contracts/scripts/calculate-hashes.ts index 71c5a8d71..7ecb66723 100644 --- a/system-contracts/scripts/calculate-hashes.ts +++ b/system-contracts/scripts/calculate-hashes.ts @@ -55,17 +55,23 @@ const getSolidityContractDetails = (dir: string, contractName: string): Contract }; const getSolidityContractsDetails = (dir: string): ContractDetails[] => { + const absolutePath = makePathAbsolute(dir); + const eligibleFiles = fs + .readdirSync(absolutePath) + .filter((f) => f.endsWith(".sol")) + .map((f) => f.replace(".sol", "")); const bytecodesDir = SOLIDITY_ARTIFACTS_DIR; const dirsEndingWithSol = findDirsEndingWith(bytecodesDir, ".sol"); - const contractNames = dirsEndingWithSol.map((d) => d.replace(".sol", "")); + const contractNames = dirsEndingWithSol.map((d) => d.replace(".sol", "")).filter((c) => eligibleFiles.includes(c)); const solidityContractsDetails = contractNames.map((c) => getSolidityContractDetails(dir, c)); return solidityContractsDetails; }; -const YUL_ARTIFACTS_DIR = "artifacts"; +const YUL_ARTIFACTS_DIR = "zkout"; const getYulContractDetails = (dir: string, contractName: string): ContractDetails => { - const bytecodePath = join(dir, YUL_ARTIFACTS_DIR, contractName + ".yul", contractName + ".yul.zbin"); + const artifactPath = dir !== "bootloader/build" ? dir : "contracts-preprocessed/bootloader"; + const bytecodePath = join(YUL_ARTIFACTS_DIR, contractName + ".yul", artifactPath, contractName + ".yul.json"); const sourceCodePath = join(dir, contractName + ".yul"); return { contractName, From 4407bf431e5812881a0b9b58b68397a62a5f3d78 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 20 Nov 2024 15:00:30 +0100 Subject: [PATCH 140/183] chore(EVM): Merge dev (#1073) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Danil Co-authored-by: kelemeno <34402761+kelemeno@users.noreply.github.com> Co-authored-by: Danil Co-authored-by: Vlad Bochok <41153528+vladbochok@users.noreply.github.com> Co-authored-by: koloz193 Co-authored-by: Grzegorz Prusak Co-authored-by: Bence Haromi <56651250+benceharomi@users.noreply.github.com> Co-authored-by: Moshe Shababo <17073733+moshababo@users.noreply.github.com> Co-authored-by: Akosh Farkash Co-authored-by: Bruno França Co-authored-by: Roman Brodetski Co-authored-by: vladbochok Co-authored-by: Stanislav Bezkorovainyi Co-authored-by: otani Co-authored-by: Ivan Schasny Co-authored-by: Ivan Schasny <31857042+ischasny@users.noreply.github.com> Co-authored-by: Thomas Nguy <81727899+thomas-nguy@users.noreply.github.com> --- .github/workflows/build-release.yaml | 30 +- .github/workflows/l1-contracts-ci.yaml | 58 ++-- .github/workflows/l2-contracts-ci.yaml | 34 ++- .github/workflows/slither.yaml | 13 +- .github/workflows/system-contracts-ci.yaml | 38 ++- .solhintignore | 1 + .../contracts/bridge/L1SharedBridge.sol | 22 +- .../contracts/common/L1ContractErrors.sol | 4 + .../governance/AccessControlRestriction.sol | 72 ----- .../contracts/governance/ChainAdmin.sol | 114 +++----- .../governance/IAccessControlRestriction.sol | 14 - .../contracts/governance/IChainAdmin.sol | 39 ++- .../governance/IPermanentRestriction.sol | 17 -- .../contracts/governance/IRestriction.sol | 15 - .../governance/PermanentRestriction.sol | 186 ------------- .../ChainConfigurationReader.s.sol | 63 +++++ l1-contracts/deploy-scripts/DeployErc20.s.sol | 2 +- l1-contracts/deploy-scripts/DeployL1.s.sol | 4 + .../deploy-scripts/DeployL2Contracts.sol | 99 +++++-- l1-contracts/deploy-scripts/EIP712Utils.sol | 30 ++ .../PrepareZKChainRegistrationCalldata.s.sol | 35 ++- .../deploy-scripts/RegisterHyperchain.s.sol | 35 +-- l1-contracts/deploy-scripts/Utils.sol | 143 ++++++++++ .../dev/SetupLegacyBridge.s.sol | 16 +- .../interfaces/IEmergencyUpgrageBoard.sol | 23 ++ .../deploy-scripts/interfaces/IMultisig.sol | 9 + .../interfaces/IProtocolUpgradeHandler.sol | 33 +++ .../deploy-scripts/interfaces/ISafe.sol | 9 + l1-contracts/script-config/.gitkeep | 0 .../script-config/artifacts/BeaconProxy.json | 81 ------ .../artifacts/L2SharedBridge.json | 262 ------------------ .../TransparentUpgradeableProxy.json | 86 ------ l1-contracts/src.ts/deploy.ts | 14 +- .../Bridgehub/experimental_bridge.t.sol | 6 +- .../Governance/AccessControlRestriction.t.sol | 186 ------------- .../governance/Governance/ChainAdmin.t.sol | 126 ++------- .../Governance/PermanentRestriction.t.sol | 211 -------------- .../test/test_config/constant/hardhat.json | 32 +-- .../dev-contracts/DevL2SharedBridge.sol | 2 +- .../dev-contracts/ITimestampAsserter.sol | 6 + .../contracts/dev-contracts/Multicall3.sol | 237 ++++++++++++++++ .../dev-contracts/TimestampAsserter.sol | 20 ++ l2-contracts/foundry.toml | 2 +- system-contracts/SystemContractsHashes.json | 116 ++++---- system-contracts/contracts/L2BaseToken.sol | 18 -- .../contracts/interfaces/IBaseToken.sol | 6 - system-contracts/foundry.toml | 1 + system-contracts/package.json | 2 +- system-contracts/scripts/calculate-hashes.ts | 20 +- .../scripts/preprocess-bootloader.ts | 34 ++- system-contracts/test/L2BaseToken.spec.ts | 21 -- 51 files changed, 1041 insertions(+), 1606 deletions(-) delete mode 100644 l1-contracts/contracts/governance/AccessControlRestriction.sol delete mode 100644 l1-contracts/contracts/governance/IAccessControlRestriction.sol delete mode 100644 l1-contracts/contracts/governance/IPermanentRestriction.sol delete mode 100644 l1-contracts/contracts/governance/IRestriction.sol delete mode 100644 l1-contracts/contracts/governance/PermanentRestriction.sol create mode 100644 l1-contracts/deploy-scripts/ChainConfigurationReader.s.sol create mode 100644 l1-contracts/deploy-scripts/EIP712Utils.sol create mode 100644 l1-contracts/deploy-scripts/interfaces/IEmergencyUpgrageBoard.sol create mode 100644 l1-contracts/deploy-scripts/interfaces/IMultisig.sol create mode 100644 l1-contracts/deploy-scripts/interfaces/IProtocolUpgradeHandler.sol create mode 100644 l1-contracts/deploy-scripts/interfaces/ISafe.sol create mode 100644 l1-contracts/script-config/.gitkeep delete mode 100644 l1-contracts/script-config/artifacts/BeaconProxy.json delete mode 100644 l1-contracts/script-config/artifacts/L2SharedBridge.json delete mode 100644 l1-contracts/script-config/artifacts/TransparentUpgradeableProxy.json delete mode 100644 l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol delete mode 100644 l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol create mode 100644 l2-contracts/contracts/dev-contracts/ITimestampAsserter.sol create mode 100644 l2-contracts/contracts/dev-contracts/Multicall3.sol create mode 100644 l2-contracts/contracts/dev-contracts/TimestampAsserter.sol diff --git a/.github/workflows/build-release.yaml b/.github/workflows/build-release.yaml index 2335b74fb..b4292e5e3 100644 --- a/.github/workflows/build-release.yaml +++ b/.github/workflows/build-release.yaml @@ -22,6 +22,15 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ inputs.commit }} + submodules: recursive + + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH - name: Use Node.js uses: actions/setup-node@v3 @@ -35,11 +44,24 @@ jobs: yarn echo "release_tag=${{ inputs.prefix }}-${{ inputs.commit }}" >> $GITHUB_OUTPUT - - name: Build contracts + - name: Build l1 contracts + working-directory: l1-contracts + run: | + forge build + + - name: Build l2 contracts + working-directory: l2-contracts + run: | + forge build --zksync --zk-enable-eravm-extensions + + - name: Build system-contracts + working-directory: system-contracts run: | - yarn l1 build - yarn l2 build - yarn sc build + yarn install + yarn preprocess:system-contracts + forge build --zksync --zk-enable-eravm-extensions + yarn preprocess:bootloader + forge build --zksync --zk-enable-eravm-extensions - name: Prepare artifacts run: | diff --git a/.github/workflows/l1-contracts-ci.yaml b/.github/workflows/l1-contracts-ci.yaml index fbf3cc770..5a27c65f8 100644 --- a/.github/workflows/l1-contracts-ci.yaml +++ b/.github/workflows/l1-contracts-ci.yaml @@ -15,6 +15,16 @@ jobs: steps: - name: Checkout the repository uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH - name: Use Node.js uses: actions/setup-node@v3 @@ -22,26 +32,25 @@ jobs: node-version: 18.18.0 cache: yarn - - name: Install dependencies - run: yarn - - - name: Build artifacts - run: yarn l1 build + - name: Build l1 contracts + working-directory: l1-contracts + run: | + forge build - - name: Build L2 artifacts - run: yarn l2 build + - name: Build l2 contracts + working-directory: l2-contracts + run: | + forge build --zksync --zk-enable-eravm-extensions - name: Create cache uses: actions/cache/save@v3 with: key: artifacts-l1-${{ github.sha }} path: | - l1-contracts/artifacts - l1-contracts/cache - l1-contracts/typechain - l2-contracts/artifacts-zk - l2-contracts/cache-zk - l2-contracts/typechain + l1-contracts/cache-forge + l1-contracts/out + l2-contracts/cache-forge + l2-contracts/zkout lint: runs-on: ubuntu-latest @@ -72,15 +81,19 @@ jobs: with: submodules: recursive - - name: Use Foundry - uses: foundry-rs/foundry-toolchain@v1 - - name: Use Node.js uses: actions/setup-node@v3 with: node-version: 18.18.0 cache: yarn + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH - name: Install dependencies run: yarn @@ -128,7 +141,7 @@ jobs: l2-contracts/typechain - name: Run tests - run: yarn l1 test --no-compile + run: yarn l1 test check-verifier-generator: runs-on: ubuntu-latest @@ -164,15 +177,20 @@ jobs: with: submodules: recursive - - name: Use Foundry - uses: foundry-rs/foundry-toolchain@v1 - - name: Use Node.js uses: actions/setup-node@v3 with: node-version: 18.18.0 cache: yarn + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH + - name: Install dependencies run: yarn diff --git a/.github/workflows/l2-contracts-ci.yaml b/.github/workflows/l2-contracts-ci.yaml index 20bb9583f..e19ac376b 100644 --- a/.github/workflows/l2-contracts-ci.yaml +++ b/.github/workflows/l2-contracts-ci.yaml @@ -10,6 +10,16 @@ jobs: steps: - name: Checkout the repository uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH - name: Use Node.js uses: actions/setup-node@v3 @@ -20,23 +30,25 @@ jobs: - name: Install dependencies run: yarn - - name: Build L1 artifacts - run: yarn l1 build + - name: Build l1 contracts + working-directory: l1-contracts + run: | + forge build - - name: Build L2 artifacts - run: yarn l2 build + - name: Build l2 contracts + working-directory: l2-contracts + run: | + forge build --zksync --zk-enable-eravm-extensions - name: Create cache uses: actions/cache/save@v3 with: - key: artifacts-l2-${{ github.sha }} + key: artifacts-l1-${{ github.sha }} path: | - l1-contracts/artifacts - l1-contracts/cache - l1-contracts/typechain - l2-contracts/artifacts-zk - l2-contracts/cache-zk - l2-contracts/typechain + l1-contracts/cache-forge + l1-contracts/out + l2-contracts/cache-forge + l2-contracts/zkout lint: runs-on: ubuntu-latest diff --git a/.github/workflows/slither.yaml b/.github/workflows/slither.yaml index fa253e159..50c9194dc 100644 --- a/.github/workflows/slither.yaml +++ b/.github/workflows/slither.yaml @@ -27,13 +27,18 @@ jobs: with: python-version: 3.8 + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH + - name: Install Slither run: | pip install slither-analyzer - - name: Use Foundry - uses: foundry-rs/foundry-toolchain@v1 - - name: Remove non-compiled files run: | rm -rf ./l1-contracts/contracts/state-transition/utils/ @@ -43,6 +48,6 @@ jobs: rm -rf ./l1-contracts/contracts/dev-contracts/test/VerifierRecursiveTest.sol - name: Run Slither + working-directory: l1-contracts run: | - cd l1-contracts slither --config ./slither.config.json . diff --git a/.github/workflows/system-contracts-ci.yaml b/.github/workflows/system-contracts-ci.yaml index 98d005a35..018a556e4 100644 --- a/.github/workflows/system-contracts-ci.yaml +++ b/.github/workflows/system-contracts-ci.yaml @@ -10,6 +10,16 @@ jobs: steps: - name: Checkout the repository uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install foundry-zksync + run: | + mkdir ./foundry-zksync + curl -LO https://github.com/matter-labs/foundry-zksync/releases/download/nightly/foundry_nightly_linux_amd64.tar.gz + tar zxf foundry_nightly_linux_amd64.tar.gz -C ./foundry-zksync + chmod +x ./foundry-zksync/forge ./foundry-zksync/cast + echo "$PWD/foundry-zksync" >> $GITHUB_PATH - name: Use Node.js uses: actions/setup-node@v3 @@ -17,22 +27,28 @@ jobs: node-version: 18.18.0 cache: yarn - - name: Install dependencies - run: yarn - - name: Build artifacts - run: yarn sc build + working-directory: system-contracts + run: | + yarn install + yarn preprocess:system-contracts + forge build --zksync --zk-enable-eravm-extensions + yarn preprocess:bootloader + forge build --zksync --zk-enable-eravm-extensions + yarn build - name: Create cache uses: actions/cache/save@v3 with: key: artifacts-system-${{ github.sha }} path: | + system-contracts/zkout + system-contracts/cache-forge + system-contracts/bootloader/build system-contracts/artifacts-zk system-contracts/cache-zk system-contracts/typechain system-contracts/contracts-preprocessed - system-contracts/bootloader/build lint: runs-on: ubuntu-latest @@ -72,11 +88,13 @@ jobs: fail-on-cache-miss: true key: artifacts-system-${{ github.sha }} path: | + system-contracts/zkout + system-contracts/cache-forge + system-contracts/bootloader/build system-contracts/artifacts-zk system-contracts/cache-zk system-contracts/typechain system-contracts/contracts-preprocessed - system-contracts/bootloader/build - name: Run bootloader tests run: | @@ -111,11 +129,13 @@ jobs: fail-on-cache-miss: true key: artifacts-system-${{ github.sha }} path: | + system-contracts/zkout + system-contracts/cache-forge + system-contracts/bootloader/build system-contracts/artifacts-zk system-contracts/cache-zk system-contracts/typechain system-contracts/contracts-preprocessed - system-contracts/bootloader/build - name: Run tests run: yarn sc test @@ -147,11 +167,13 @@ jobs: fail-on-cache-miss: true key: artifacts-system-${{ github.sha }} path: | + system-contracts/zkout + system-contracts/cache-forge + system-contracts/bootloader/build system-contracts/artifacts-zk system-contracts/cache-zk system-contracts/typechain system-contracts/contracts-preprocessed - system-contracts/bootloader/build - name: Check hashes run: yarn sc calculate-hashes:check diff --git a/.solhintignore b/.solhintignore index 2371ed166..785a7e178 100644 --- a/.solhintignore +++ b/.solhintignore @@ -17,6 +17,7 @@ l1-contracts-foundry/lib # l2-contracts l2-contracts/cache-zk l2-contracts/node_modules +l2-contracts/contracts/dev-contracts # system-contracts system-contracts/contracts/openzeppelin diff --git a/l1-contracts/contracts/bridge/L1SharedBridge.sol b/l1-contracts/contracts/bridge/L1SharedBridge.sol index eaddcccc7..1f81887bb 100644 --- a/l1-contracts/contracts/bridge/L1SharedBridge.sol +++ b/l1-contracts/contracts/bridge/L1SharedBridge.sol @@ -22,7 +22,7 @@ import {ETH_TOKEN_ADDRESS, TWO_BRIDGES_MAGIC_VALUE} from "../common/Config.sol"; import {IBridgehub, L2TransactionRequestTwoBridgesInner, L2TransactionRequestDirect} from "../bridgehub/IBridgehub.sol"; import {IGetters} from "../state-transition/chain-interfaces/IGetters.sol"; import {L2_BASE_TOKEN_SYSTEM_CONTRACT_ADDR} from "../common/L2ContractAddresses.sol"; -import {Unauthorized, ZeroAddress, SharedBridgeValueAlreadySet, SharedBridgeKey, NoFundsTransferred, ZeroBalance, ValueMismatch, TokensWithFeesNotSupported, NonEmptyMsgValue, L2BridgeNotSet, TokenNotSupported, DepositIncorrectAmount, EmptyDeposit, DepositExists, AddressAlreadyUsed, InvalidProof, DepositDoesNotExist, InsufficientChainBalance, SharedBridgeValueNotSet, WithdrawalAlreadyFinalized, WithdrawFailed, L2WithdrawalMessageWrongLength, InvalidSelector, SharedBridgeBalanceMismatch, SharedBridgeValueNotSet} from "../common/L1ContractErrors.sol"; +import {Unauthorized, ZeroAddress, SharedBridgeValueAlreadySet, SharedBridgeKey, NoFundsTransferred, ZeroBalance, ValueMismatch, TokensWithFeesNotSupported, NonEmptyMsgValue, L2BridgeNotSet, TokenNotSupported, DepositIncorrectAmount, EmptyDeposit, DepositExists, AddressAlreadyUsed, InvalidProof, DepositDoesNotExist, InsufficientChainBalance, SharedBridgeValueNotSet, WithdrawalAlreadyFinalized, WithdrawFailed, L2WithdrawalMessageWrongLength, InvalidSelector, SharedBridgeBalanceMismatch, SharedBridgeValueNotSet, NotPendingAdmin, L2BridgeAlreadySet} from "../common/L1ContractErrors.sol"; /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev @@ -130,7 +130,9 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Ownable2StepUpgrade /// @notice Checks that the message sender is either the owner or admin. modifier onlyOwnerOrAdmin() { - require(msg.sender == owner() || msg.sender == admin, "ShB not owner or admin"); + if (msg.sender != owner() && msg.sender != admin) { + revert Unauthorized(msg.sender); + } _; } @@ -174,7 +176,9 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Ownable2StepUpgrade /// @notice Accepts transfer of admin rights. Only pending admin can accept the role. function acceptAdmin() external { address currentPendingAdmin = pendingAdmin; - require(msg.sender == currentPendingAdmin, "ShB not pending admin"); // Only proposed by current admin address can claim the admin rights + if (msg.sender != currentPendingAdmin) { + revert NotPendingAdmin(); + } address previousAdmin = admin; admin = currentPendingAdmin; @@ -276,8 +280,12 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Ownable2StepUpgrade /// @param _chainId The chain ID for which the l2Bridge address is being initialized. /// @param _l2BridgeAddress The address of the L2 bridge contract. function initializeChainGovernance(uint256 _chainId, address _l2BridgeAddress) external onlyOwnerOrAdmin { - require(l2BridgeAddress[_chainId] == address(0), "ShB: l2 bridge already set"); - require(_l2BridgeAddress != address(0), "ShB: l2 bridge 0"); + if (l2BridgeAddress[_chainId] != address(0)) { + revert L2BridgeAlreadySet(_chainId); + } + if (_l2BridgeAddress == address(0)) { + revert ZeroAddress(); + } l2BridgeAddress[_chainId] = _l2BridgeAddress; } @@ -287,7 +295,9 @@ contract L1SharedBridge is IL1SharedBridge, ReentrancyGuard, Ownable2StepUpgrade /// @param _chainId The chain ID for which the l2Bridge address is being initialized. /// @param _l2BridgeAddress The address of the L2 bridge contract. function reinitializeChainGovernance(uint256 _chainId, address _l2BridgeAddress) external onlyOwner { - require(l2BridgeAddress[_chainId] != address(0), "ShB: l2 bridge not yet set"); + if (l2BridgeAddress[_chainId] == address(0)) { + revert L2BridgeNotSet(_chainId); + } l2BridgeAddress[_chainId] = _l2BridgeAddress; } diff --git a/l1-contracts/contracts/common/L1ContractErrors.sol b/l1-contracts/contracts/common/L1ContractErrors.sol index bec5a56cd..62ff78917 100644 --- a/l1-contracts/contracts/common/L1ContractErrors.sol +++ b/l1-contracts/contracts/common/L1ContractErrors.sol @@ -137,6 +137,8 @@ error InvalidValue(); error L2BridgeNotDeployed(uint256 chainId); // 0xff8811ff error L2BridgeNotSet(uint256 chainId); +// 0x685577fa +error L2BridgeAlreadySet(uint256 chainId); // 0xcb5e4247 error L2BytecodeHashMismatch(bytes32 expected, bytes32 provided); // 0xfb5c22e6 @@ -193,6 +195,8 @@ error NonZeroAddress(address); error NotEnoughGas(); // 0xdd7e3621 error NotInitializedReentrancyGuard(); +// 0x058d9a1b +error NotPendingAdmin(); // 0xf3ed9dfa error OnlyEraSupported(); // 0x1a21feed diff --git a/l1-contracts/contracts/governance/AccessControlRestriction.sol b/l1-contracts/contracts/governance/AccessControlRestriction.sol deleted file mode 100644 index 3fc67f875..000000000 --- a/l1-contracts/contracts/governance/AccessControlRestriction.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -import {AccessToFallbackDenied, AccessToFunctionDenied} from "../common/L1ContractErrors.sol"; -import {IAccessControlRestriction} from "./IAccessControlRestriction.sol"; -import {AccessControlDefaultAdminRules} from "@openzeppelin/contracts-v4/access/AccessControlDefaultAdminRules.sol"; -import {IRestriction} from "./IRestriction.sol"; -import {Call} from "./Common.sol"; - -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -/// @notice The Restriction that is designed to provide the access control logic for the `ChainAdmin` contract. -/// @dev It inherits from `AccessControlDefaultAdminRules` without overriding `_setRoleAdmin` functionaity. In other -/// words, the `DEFAULT_ADMIN_ROLE` is the only role that can manage roles. This is done for simplicity. -/// @dev An instance of this restriction should be deployed separately for each `ChainAdmin` contract. -/// @dev IMPORTANT: this function does not validate the ability of the invoker to use `msg.value`. Thus, -/// either all callers with access to functions should be trusted to not steal ETH from the `ChainAdmin` account -/// or not ETH should be passively stored in `ChainAdmin` account. -contract AccessControlRestriction is IRestriction, IAccessControlRestriction, AccessControlDefaultAdminRules { - /// @notice Required roles to call a specific functions. - /// @dev Note, that the role 0 means the `DEFAULT_ADMIN_ROLE` from the `AccessControlDefaultAdminRules` contract. - mapping(address target => mapping(bytes4 selector => bytes32 requiredRole)) public requiredRoles; - - /// @notice Required roles to call a fallback function. - mapping(address target => bytes32 requiredRole) public requiredRolesForFallback; - - constructor( - uint48 initialDelay, - address initialDefaultAdmin - ) AccessControlDefaultAdminRules(initialDelay, initialDefaultAdmin) {} - - /// @notice Sets the required role for a specific function call. - /// @param _target The address of the contract. - /// @param _selector The selector of the function. - /// @param _requiredRole The required role. - function setRequiredRoleForCall( - address _target, - bytes4 _selector, - bytes32 _requiredRole - ) external onlyRole(DEFAULT_ADMIN_ROLE) { - requiredRoles[_target][_selector] = _requiredRole; - - emit RoleSet(_target, _selector, _requiredRole); - } - - /// @notice Sets the required role for a fallback function call. - /// @param _target The address of the contract. - /// @param _requiredRole The required role. - function setRequiredRoleForFallback(address _target, bytes32 _requiredRole) external onlyRole(DEFAULT_ADMIN_ROLE) { - requiredRolesForFallback[_target] = _requiredRole; - - emit FallbackRoleSet(_target, _requiredRole); - } - - /// @inheritdoc IRestriction - function validateCall(Call calldata _call, address _invoker) external view { - // Note, that since `DEFAULT_ADMIN_ROLE` is 0 and the default storage value for the - // `requiredRoles` and `requiredRolesForFallback` is 0, the default admin is by default a required - // role for all the functions. - if (_call.data.length < 4) { - if (!hasRole(requiredRolesForFallback[_call.target], _invoker)) { - revert AccessToFallbackDenied(_call.target, _invoker); - } - } else { - bytes4 selector = bytes4(_call.data[:4]); - if (!hasRole(requiredRoles[_call.target][selector], _invoker)) { - revert AccessToFunctionDenied(_call.target, selector, _invoker); - } - } - } -} diff --git a/l1-contracts/contracts/governance/ChainAdmin.sol b/l1-contracts/contracts/governance/ChainAdmin.sol index f6a93146f..4d9ff858f 100644 --- a/l1-contracts/contracts/governance/ChainAdmin.sol +++ b/l1-contracts/contracts/governance/ChainAdmin.sol @@ -2,76 +2,48 @@ pragma solidity 0.8.24; -// solhint-disable gas-length-in-loops - -import {NoCallsProvided, OnlySelfAllowed, RestrictionWasNotPresent, RestrictionWasAlreadyPresent} from "../common/L1ContractErrors.sol"; +import {Ownable2Step} from "@openzeppelin/contracts-v4/access/Ownable2Step.sol"; import {IChainAdmin} from "./IChainAdmin.sol"; -import {IRestriction} from "./IRestriction.sol"; -import {Call} from "./Common.sol"; - -import {EnumerableSet} from "@openzeppelin/contracts-v4/utils/structs/EnumerableSet.sol"; -import {ReentrancyGuard} from "../common/ReentrancyGuard.sol"; +import {IAdmin} from "../state-transition/chain-interfaces/IAdmin.sol"; +import {NoCallsProvided, Unauthorized, ZeroAddress} from "../common/L1ContractErrors.sol"; /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev /// @notice The contract is designed to hold the `admin` role in ZKSync Chain (State Transition) contracts. /// The owner of the contract can perform any external calls and also save the information needed for -/// the blockchain node to accept the protocol upgrade. -contract ChainAdmin is IChainAdmin, ReentrancyGuard { - using EnumerableSet for EnumerableSet.AddressSet; - - /// @notice Ensures that only the `ChainAdmin` contract itself can call the function. - /// @dev All functions that require access-control should use `onlySelf` modifier, while the access control logic - /// should be implemented in the restriction contracts. - modifier onlySelf() { - if (msg.sender != address(this)) { - revert OnlySelfAllowed(); - } - _; - } - - constructor(address[] memory _initialRestrictions) reentrancyGuardInitializer { - unchecked { - for (uint256 i = 0; i < _initialRestrictions.length; ++i) { - _addRestriction(_initialRestrictions[i]); - } - } - } - +/// the blockchain node to accept the protocol upgrade. Another role - `tokenMultiplierSetter` can be used in the contract +/// to change the base token gas price in the Chain contract. +contract ChainAdmin is IChainAdmin, Ownable2Step { /// @notice Mapping of protocol versions to their expected upgrade timestamps. /// @dev Needed for the offchain node administration to know when to start building batches with the new protocol version. mapping(uint256 protocolVersion => uint256 upgradeTimestamp) public protocolVersionToUpgradeTimestamp; - /// @notice The set of active restrictions. - EnumerableSet.AddressSet internal activeRestrictions; - - /// @notice Returns the list of active restrictions. - function getRestrictions() public view returns (address[] memory) { - return activeRestrictions.values(); - } - - /// @inheritdoc IChainAdmin - function isRestrictionActive(address _restriction) external view returns (bool) { - return activeRestrictions.contains(_restriction); - } + /// @notice The address which can call `setTokenMultiplier` function to change the base token gas price in the Chain contract. + /// @dev The token base price can be changed quite often, so the private key for this role is supposed to be stored in the node + /// and used by the automated service in a way similar to the sequencer workflow. + address public tokenMultiplierSetter; - /// @inheritdoc IChainAdmin - function addRestriction(address _restriction) external onlySelf { - _addRestriction(_restriction); + constructor(address _initialOwner, address _initialTokenMultiplierSetter) { + if (_initialOwner == address(0)) { + revert ZeroAddress(); + } + _transferOwnership(_initialOwner); + // Can be zero if no one has this permission. + tokenMultiplierSetter = _initialTokenMultiplierSetter; + emit NewTokenMultiplierSetter(address(0), _initialTokenMultiplierSetter); } - /// @inheritdoc IChainAdmin - function removeRestriction(address _restriction) external onlySelf { - if (!activeRestrictions.remove(_restriction)) { - revert RestrictionWasNotPresent(_restriction); - } - emit RestrictionRemoved(_restriction); + /// @notice Updates the address responsible for setting token multipliers on the Chain contract . + /// @param _tokenMultiplierSetter The new address to be set as the token multiplier setter. + function setTokenMultiplierSetter(address _tokenMultiplierSetter) external onlyOwner { + emit NewTokenMultiplierSetter(tokenMultiplierSetter, _tokenMultiplierSetter); + tokenMultiplierSetter = _tokenMultiplierSetter; } /// @notice Set the expected upgrade timestamp for a specific protocol version. /// @param _protocolVersion The ZKsync chain protocol version. /// @param _upgradeTimestamp The timestamp at which the chain node should expect the upgrade to happen. - function setUpgradeTimestamp(uint256 _protocolVersion, uint256 _upgradeTimestamp) external onlySelf { + function setUpgradeTimestamp(uint256 _protocolVersion, uint256 _upgradeTimestamp) external onlyOwner { protocolVersionToUpgradeTimestamp[_protocolVersion] = _upgradeTimestamp; emit UpdateUpgradeTimestamp(_protocolVersion, _upgradeTimestamp); } @@ -80,16 +52,12 @@ contract ChainAdmin is IChainAdmin, ReentrancyGuard { /// @param _calls Array of Call structures defining target, value, and data for each call. /// @param _requireSuccess If true, reverts transaction on any call failure. /// @dev Intended for batch processing of contract interactions, managing gas efficiency and atomicity of operations. - /// @dev Note, that this function lacks access control. It is expected that the access control is implemented in a separate restriction contract. - /// @dev Even though all the validation from external modules is executed via `staticcall`, the function - /// is marked as `nonReentrant` to prevent reentrancy attacks in case the staticcall restriction is lifted in the future. - function multicall(Call[] calldata _calls, bool _requireSuccess) external payable nonReentrant { + function multicall(Call[] calldata _calls, bool _requireSuccess) external payable onlyOwner { if (_calls.length == 0) { revert NoCallsProvided(); } + // solhint-disable-next-line gas-length-in-loops for (uint256 i = 0; i < _calls.length; ++i) { - _validateCall(_calls[i]); - // slither-disable-next-line arbitrary-send-eth (bool success, bytes memory returnData) = _calls[i].target.call{value: _calls[i].value}(_calls[i].data); if (_requireSuccess && !success) { @@ -102,27 +70,17 @@ contract ChainAdmin is IChainAdmin, ReentrancyGuard { } } - /// @dev Contract might receive/hold ETH as part of the maintenance process. - receive() external payable {} - - /// @notice Function that returns the current admin can perform the call. - /// @dev By default it always returns true, but can be overridden in derived contracts. - function _validateCall(Call calldata _call) internal view { - address[] memory restrictions = getRestrictions(); - - unchecked { - for (uint256 i = 0; i < restrictions.length; ++i) { - IRestriction(restrictions[i]).validateCall(_call, msg.sender); - } + /// @notice Sets the token multiplier in the specified Chain contract. + /// @param _chainContract The chain contract address where the token multiplier will be set. + /// @param _nominator The numerator part of the token multiplier. + /// @param _denominator The denominator part of the token multiplier. + function setTokenMultiplier(IAdmin _chainContract, uint128 _nominator, uint128 _denominator) external { + if (msg.sender != tokenMultiplierSetter) { + revert Unauthorized(msg.sender); } + _chainContract.setTokenMultiplier(_nominator, _denominator); } - /// @notice Adds a new restriction to the active restrictions set. - /// @param _restriction The address of the restriction contract to be added. - function _addRestriction(address _restriction) internal { - if (!activeRestrictions.add(_restriction)) { - revert RestrictionWasAlreadyPresent(_restriction); - } - emit RestrictionAdded(_restriction); - } + /// @dev Contract might receive/hold ETH as part of the maintenance process. + receive() external payable {} } diff --git a/l1-contracts/contracts/governance/IAccessControlRestriction.sol b/l1-contracts/contracts/governance/IAccessControlRestriction.sol deleted file mode 100644 index 3c9cfb5c5..000000000 --- a/l1-contracts/contracts/governance/IAccessControlRestriction.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -/// @title AccessControlRestriction contract interface -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -interface IAccessControlRestriction { - /// @notice Emitted when the required role for a specific function is set. - event RoleSet(address indexed target, bytes4 indexed selector, bytes32 requiredRole); - - /// @notice Emitted when the required role for a fallback function is set. - event FallbackRoleSet(address indexed target, bytes32 requiredRole); -} diff --git a/l1-contracts/contracts/governance/IChainAdmin.sol b/l1-contracts/contracts/governance/IChainAdmin.sol index 1ef3144c2..d5d8f117c 100644 --- a/l1-contracts/contracts/governance/IChainAdmin.sol +++ b/l1-contracts/contracts/governance/IChainAdmin.sol @@ -2,37 +2,36 @@ pragma solidity 0.8.24; -import {Call} from "./Common.sol"; +import {IAdmin} from "../state-transition/chain-interfaces/IAdmin.sol"; /// @title ChainAdmin contract interface /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev interface IChainAdmin { + /// @dev Represents a call to be made during multicall. + /// @param target The address to which the call will be made. + /// @param value The amount of Ether (in wei) to be sent along with the call. + /// @param data The calldata to be executed on the `target` address. + struct Call { + address target; + uint256 value; + bytes data; + } + /// @notice Emitted when the expected upgrade timestamp for a specific protocol version is set. - event UpdateUpgradeTimestamp(uint256 indexed protocolVersion, uint256 upgradeTimestamp); + event UpdateUpgradeTimestamp(uint256 indexed _protocolVersion, uint256 _upgradeTimestamp); /// @notice Emitted when the call is executed from the contract. - event CallExecuted(Call call, bool success, bytes returnData); - - /// @notice Emitted when a new restriction is added. - event RestrictionAdded(address indexed restriction); + event CallExecuted(Call _call, bool _success, bytes _returnData); - /// @notice Emitted when a restriction is removed. - event RestrictionRemoved(address indexed restriction); + /// @notice Emitted when the new token multiplier address is set. + event NewTokenMultiplierSetter(address _oldTokenMultiplierSetter, address _newTokenMultiplierSetter); - /// @notice Returns the list of active restrictions. - function getRestrictions() external view returns (address[] memory); + function setTokenMultiplierSetter(address _tokenMultiplierSetter) external; - /// @notice Checks if the restriction is active. - /// @param _restriction The address of the restriction contract. - function isRestrictionActive(address _restriction) external view returns (bool); + function setUpgradeTimestamp(uint256 _protocolVersion, uint256 _upgradeTimestamp) external; - /// @notice Adds a new restriction to the active restrictions set. - /// @param _restriction The address of the restriction contract. - function addRestriction(address _restriction) external; + function multicall(Call[] calldata _calls, bool _requireSuccess) external payable; - /// @notice Removes a restriction from the active restrictions set. - /// @param _restriction The address of the restriction contract. - /// @dev Sometimes restrictions might need to enforce their permanence (e.g. if a chain should be a rollup forever). - function removeRestriction(address _restriction) external; + function setTokenMultiplier(IAdmin _chainContract, uint128 _nominator, uint128 _denominator) external; } diff --git a/l1-contracts/contracts/governance/IPermanentRestriction.sol b/l1-contracts/contracts/governance/IPermanentRestriction.sol deleted file mode 100644 index 548866b9f..000000000 --- a/l1-contracts/contracts/governance/IPermanentRestriction.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -/// @notice The interface for the permanent restriction contract. -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -interface IPermanentRestriction { - /// @notice Emitted when the implementation is allowed or disallowed. - event AdminImplementationAllowed(bytes32 indexed implementationHash, bool isAllowed); - - /// @notice Emitted when a certain calldata is allowed or disallowed. - event AllowedDataChanged(bytes data, bool isAllowed); - - /// @notice Emitted when the selector is labeled as validated or not. - event SelectorValidationChanged(bytes4 indexed selector, bool isValidated); -} diff --git a/l1-contracts/contracts/governance/IRestriction.sol b/l1-contracts/contracts/governance/IRestriction.sol deleted file mode 100644 index b2cc79428..000000000 --- a/l1-contracts/contracts/governance/IRestriction.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -import {Call} from "./Common.sol"; - -/// @title Restriction contract interface -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -interface IRestriction { - /// @notice Ensures that the invoker has the required role to call the function. - /// @param _call The call data. - /// @param _invoker The address of the invoker. - function validateCall(Call calldata _call, address _invoker) external view; -} diff --git a/l1-contracts/contracts/governance/PermanentRestriction.sol b/l1-contracts/contracts/governance/PermanentRestriction.sol deleted file mode 100644 index acf75a67f..000000000 --- a/l1-contracts/contracts/governance/PermanentRestriction.sol +++ /dev/null @@ -1,186 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.24; - -import {CallNotAllowed, ChainZeroAddress, NotAHyperchain, NotAnAdmin, RemovingPermanentRestriction, ZeroAddress, UnallowedImplementation} from "../common/L1ContractErrors.sol"; - -import {Ownable2Step} from "@openzeppelin/contracts-v4/access/Ownable2Step.sol"; - -import {Call} from "./Common.sol"; -import {IRestriction} from "./IRestriction.sol"; -import {IChainAdmin} from "./IChainAdmin.sol"; -import {IBridgehub} from "../bridgehub/IBridgehub.sol"; -import {IZkSyncHyperchain} from "../state-transition/chain-interfaces/IZkSyncHyperchain.sol"; -import {IAdmin} from "../state-transition/chain-interfaces/IAdmin.sol"; - -import {IPermanentRestriction} from "./IPermanentRestriction.sol"; - -/// @title PermanentRestriction contract -/// @author Matter Labs -/// @custom:security-contact security@matterlabs.dev -/// @notice This contract should be used by chains that wish to guarantee that certain security -/// properties are preserved forever. -/// @dev To be deployed as a transparent upgradable proxy, owned by a trusted decentralized governance. -/// @dev Once of the instances of such contract is to ensure that a ZkSyncHyperchain is a rollup forever. -contract PermanentRestriction is IRestriction, IPermanentRestriction, Ownable2Step { - /// @notice The address of the Bridgehub contract. - IBridgehub public immutable BRIDGE_HUB; - - /// @notice The mapping of the allowed admin implementations. - mapping(bytes32 implementationCodeHash => bool isAllowed) public allowedAdminImplementations; - - /// @notice The mapping of the allowed calls. - mapping(bytes allowedCalldata => bool isAllowed) public allowedCalls; - - /// @notice The mapping of the validated selectors. - mapping(bytes4 selector => bool isValidated) public validatedSelectors; - - constructor(address _initialOwner, IBridgehub _bridgehub) { - BRIDGE_HUB = _bridgehub; - - // solhint-disable-next-line gas-custom-errors, reason-string - if (_initialOwner == address(0)) { - revert ZeroAddress(); - } - _transferOwnership(_initialOwner); - } - - /// @notice Allows a certain `ChainAdmin` implementation to be used as an admin. - /// @param _implementationHash The hash of the implementation code. - /// @param _isAllowed The flag that indicates if the implementation is allowed. - function allowAdminImplementation(bytes32 _implementationHash, bool _isAllowed) external onlyOwner { - allowedAdminImplementations[_implementationHash] = _isAllowed; - - emit AdminImplementationAllowed(_implementationHash, _isAllowed); - } - - /// @notice Allows a certain calldata for a selector to be used. - /// @param _data The calldata for the function. - /// @param _isAllowed The flag that indicates if the calldata is allowed. - function setAllowedData(bytes calldata _data, bool _isAllowed) external onlyOwner { - allowedCalls[_data] = _isAllowed; - - emit AllowedDataChanged(_data, _isAllowed); - } - - /// @notice Allows a certain selector to be validated. - /// @param _selector The selector of the function. - /// @param _isValidated The flag that indicates if the selector is validated. - function setSelectorIsValidated(bytes4 _selector, bool _isValidated) external onlyOwner { - validatedSelectors[_selector] = _isValidated; - - emit SelectorValidationChanged(_selector, _isValidated); - } - - /// @inheritdoc IRestriction - function validateCall( - Call calldata _call, - address // _invoker - ) external view override { - _validateAsChainAdmin(_call); - _validateRemoveRestriction(_call); - } - - /// @notice Validates the call as the chain admin - /// @param _call The call data. - function _validateAsChainAdmin(Call calldata _call) internal view { - if (!_isAdminOfAChain(_call.target)) { - // We only validate calls related to being an admin of a chain - return; - } - - // All calls with the length of the data below 4 will get into `receive`/`fallback` functions, - // we consider it to always be allowed. - if (_call.data.length < 4) { - return; - } - - bytes4 selector = bytes4(_call.data[:4]); - - if (selector == IAdmin.setPendingAdmin.selector) { - _validateNewAdmin(_call); - return; - } - - if (!validatedSelectors[selector]) { - // The selector is not validated, any data is allowed. - return; - } - - if (!allowedCalls[_call.data]) { - revert CallNotAllowed(_call.data); - } - } - - /// @notice Validates the correctness of the new admin. - /// @param _call The call data. - /// @dev Ensures that the admin has a whitelisted implementation and does not remove this restriction. - function _validateNewAdmin(Call calldata _call) internal view { - address newChainAdmin = abi.decode(_call.data[4:], (address)); - - bytes32 implementationCodeHash = newChainAdmin.codehash; - - if (!allowedAdminImplementations[implementationCodeHash]) { - revert UnallowedImplementation(implementationCodeHash); - } - - // Since the implementation is known to be correct (from the checks above), we - // can safely trust the returned value from the call below - if (!IChainAdmin(newChainAdmin).isRestrictionActive(address(this))) { - revert RemovingPermanentRestriction(); - } - } - - /// @notice Validates the removal of the restriction. - /// @param _call The call data. - /// @dev Ensures that this restriction is not removed. - function _validateRemoveRestriction(Call calldata _call) internal view { - if (_call.target != msg.sender) { - return; - } - - if (bytes4(_call.data[:4]) != IChainAdmin.removeRestriction.selector) { - return; - } - - address removedRestriction = abi.decode(_call.data[4:], (address)); - - if (removedRestriction == address(this)) { - revert RemovingPermanentRestriction(); - } - } - - /// @notice Checks if the `msg.sender` is an admin of a certain ZkSyncHyperchain. - /// @param _chain The address of the chain. - function _isAdminOfAChain(address _chain) internal view returns (bool) { - (bool success, ) = address(this).staticcall(abi.encodeCall(this.tryCompareAdminOfAChain, (_chain, msg.sender))); - return success; - } - - /// @notice Tries to compare the admin of a chain with the potential admin. - /// @param _chain The address of the chain. - /// @param _potentialAdmin The address of the potential admin. - /// @dev This function reverts if the `_chain` is not a ZkSyncHyperchain or the `_potentialAdmin` is not the - /// admin of the chain. - function tryCompareAdminOfAChain(address _chain, address _potentialAdmin) external view { - if (_chain == address(0)) { - revert ChainZeroAddress(); - } - - // Unfortunately there is no easy way to double check that indeed the `_chain` is a ZkSyncHyperchain. - // So we do the following: - // - Query it for `chainId`. If it reverts, it is not a ZkSyncHyperchain. - // - Query the Bridgehub for the Hyperchain with the given `chainId`. - // - We compare the corresponding addresses - uint256 chainId = IZkSyncHyperchain(_chain).getChainId(); - if (BRIDGE_HUB.getHyperchain(chainId) != _chain) { - revert NotAHyperchain(_chain); - } - - // Now, the chain is known to be a hyperchain, so it should implement the corresponding interface - address admin = IZkSyncHyperchain(_chain).getAdmin(); - if (admin != _potentialAdmin) { - revert NotAnAdmin(admin, _potentialAdmin); - } - } -} diff --git a/l1-contracts/deploy-scripts/ChainConfigurationReader.s.sol b/l1-contracts/deploy-scripts/ChainConfigurationReader.s.sol new file mode 100644 index 000000000..54a9ebe8a --- /dev/null +++ b/l1-contracts/deploy-scripts/ChainConfigurationReader.s.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.21; + +import {Script, console2 as console} from "forge-std/Script.sol"; +import {Vm} from "forge-std/Vm.sol"; +import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol"; +import {PubdataPricingMode} from "contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol"; +import {StateTransitionManager} from "contracts/state-transition/StateTransitionManager.sol"; +import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol"; +import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; + +contract ChainConfigurationReader is Script { + function run(address stmAddress, uint256 chainId) public { + StateTransitionManager stm = StateTransitionManager(stmAddress); + IZkSyncHyperchain diamondProxy = IZkSyncHyperchain(stm.getHyperchain(chainId)); + address payable chainAdmin = payable(stm.getChainAdmin(chainId)); + address tokenMultiplierSetter = ChainAdmin(chainAdmin).tokenMultiplierSetter(); + address owner = ChainAdmin(chainAdmin).owner(); + address basetoken = diamondProxy.getBaseToken(); + (uint32 major, uint32 minor, uint32 patch) = diamondProxy.getSemverProtocolVersion(); + address validatorTimelock = stm.validatorTimelock(); + PubdataPricingMode pubdataPricingMode = diamondProxy.getPubdataPricingMode(); + + uint256 baseTokenGasPriceMultiplierNominator = diamondProxy.baseTokenGasPriceMultiplierNominator(); + uint256 baseTokenGasPriceMultiplierDenominator = diamondProxy.baseTokenGasPriceMultiplierDenominator(); + + console.log("=====INFO ABOUT CHAIN %d =====", chainId); + console.log("Diamond Proxy %s", address(diamondProxy)); + console.log("ChainAdmin %s", chainAdmin); + console.log("Token Multiplier Setter of ChainAdmin %s", tokenMultiplierSetter); + console.log("Owner of ChainAdmin %s", owner); + console.log("Protocol Version %d.%d.%d", major, minor, patch); + if (pubdataPricingMode == PubdataPricingMode.Validium) { + console.log("Pubdata Pricing Mode: Validium"); + } else if (pubdataPricingMode == PubdataPricingMode.Rollup) { + console.log("Pubdata Pricing Mode: Rollup"); + } + + console.log("==Validators=="); + getNewValidators(validatorTimelock, chainId); + console.log("==BASE TOKEN=="); + console.log("address: %s", basetoken); + console.log("nominator: %s", baseTokenGasPriceMultiplierNominator); + console.log("denominator: %s", baseTokenGasPriceMultiplierDenominator); + } + + function getNewValidators(address validatorTimelock, uint256 chainId) internal { + bytes32[] memory topics = new bytes32[](2); + topics[0] = ValidatorTimelock.ValidatorAdded.selector; + topics[1] = bytes32(chainId); + Vm.EthGetLogs[] memory logs = vm.eth_getLogs(1, block.number, validatorTimelock, topics); + for (uint256 i = 0; i < logs.length; i++) { + Vm.EthGetLogs memory log = logs[i]; + console.log("New Validator", bytesToAddress(log.data)); + } + } + + function bytesToAddress(bytes memory bys) private pure returns (address addr) { + assembly { + addr := mload(add(bys, 32)) + } + } +} diff --git a/l1-contracts/deploy-scripts/DeployErc20.s.sol b/l1-contracts/deploy-scripts/DeployErc20.s.sol index 60f34230a..9a7c9cfa9 100644 --- a/l1-contracts/deploy-scripts/DeployErc20.s.sol +++ b/l1-contracts/deploy-scripts/DeployErc20.s.sol @@ -83,7 +83,7 @@ contract DeployErc20Script is Script { function deployTokens() internal { uint256 tokensLength = config.tokens.length; for (uint256 i = 0; i < tokensLength; ++i) { - TokenDescription memory token = config.tokens[i]; + TokenDescription storage token = config.tokens[i]; console.log("Deploying token:", token.name); address tokenAddress = deployErc20({ name: token.name, diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index bca9c53ef..3dd7da0b0 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -602,12 +602,15 @@ contract DeployL1Script is Script { Bridgehub bridgehub = Bridgehub(addresses.bridgehub.bridgehubProxy); bridgehub.transferOwnership(addresses.governance); + bridgehub.setPendingAdmin(addresses.chainAdmin); L1SharedBridge sharedBridge = L1SharedBridge(addresses.bridges.sharedBridgeProxy); sharedBridge.transferOwnership(addresses.governance); + sharedBridge.setPendingAdmin(addresses.chainAdmin); StateTransitionManager stm = StateTransitionManager(addresses.stateTransition.stateTransitionProxy); stm.transferOwnership(addresses.governance); + stm.setPendingAdmin(addresses.chainAdmin); vm.stopBroadcast(); console.log("Owners updated"); @@ -718,6 +721,7 @@ contract DeployL1Script is Script { addresses.blobVersionedHashRetriever ); vm.serializeAddress("deployed_addresses", "validator_timelock_addr", addresses.validatorTimelock); + vm.serializeAddress("deployed_addresses", "chain_admin", addresses.chainAdmin); vm.serializeString("deployed_addresses", "bridgehub", bridgehub); vm.serializeString("deployed_addresses", "state_transition", stateTransition); string memory deployedAddresses = vm.serializeString("deployed_addresses", "bridges", bridges); diff --git a/l1-contracts/deploy-scripts/DeployL2Contracts.sol b/l1-contracts/deploy-scripts/DeployL2Contracts.sol index fb3f35024..899cc9263 100644 --- a/l1-contracts/deploy-scripts/DeployL2Contracts.sol +++ b/l1-contracts/deploy-scripts/DeployL2Contracts.sol @@ -31,7 +31,9 @@ contract DeployL2Script is Script { address l2SharedBridgeProxy; address consensusRegistryImplementation; address consensusRegistryProxy; + address multicall3; address forceDeployUpgraderAddress; + address timestampAsserter; } struct ContractsBytecodes { @@ -42,7 +44,9 @@ contract DeployL2Script is Script { bytes l2SharedBridgeProxyBytecode; bytes consensusRegistryBytecode; bytes consensusRegistryProxyBytecode; + bytes multicall3Bytecode; bytes forceDeployUpgrader; + bytes timestampAsserterBytecode; } function run() public { @@ -64,6 +68,8 @@ contract DeployL2Script is Script { deployForceDeployer(); deployConsensusRegistry(); deployConsensusRegistryProxy(); + deployMulticall3(); + deployTimestampAsserter(); saveOutput(); } @@ -107,42 +113,66 @@ contract DeployL2Script is Script { saveOutput(); } + function runDeployMulticall3() public { + initializeConfig(); + loadContracts(false); + + deployMulticall3(); + + saveOutput(); + } + + function runDeployTimestampAsserter() public { + initializeConfig(); + loadContracts(false); + + deployTimestampAsserter(); + + saveOutput(); + } + function loadContracts(bool legacyBridge) internal { //HACK: Meanwhile we are not integrated foundry zksync we use contracts that has been built using hardhat - contracts.l2StandardErc20FactoryBytecode = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/beacon/UpgradeableBeacon.sol/UpgradeableBeacon.json" + contracts.l2StandardErc20FactoryBytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/UpgradeableBeacon.sol/UpgradeableBeacon.json" ); - contracts.beaconProxy = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol/BeaconProxy.json" - ); - contracts.l2StandardErc20Bytecode = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/contracts/bridge/L2StandardERC20.sol/L2StandardERC20.json" + contracts.beaconProxy = Utils.readFoundryBytecode("/../l2-contracts/zkout/BeaconProxy.sol/BeaconProxy.json"); + contracts.l2StandardErc20Bytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/L2StandardERC20.sol/L2StandardERC20.json" ); if (legacyBridge) { - contracts.l2SharedBridgeBytecode = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/contracts/dev-contracts/DevL2SharedBridge.sol/DevL2SharedBridge.json" + contracts.l2SharedBridgeBytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/DevL2SharedBridge.sol/DevL2SharedBridge.json" ); } else { - contracts.l2SharedBridgeBytecode = Utils.readHardhatBytecode( + contracts.l2SharedBridgeBytecode = Utils.readFoundryBytecode( "/../l2-contracts/zkout/L2SharedBridge.sol/L2SharedBridge.json" ); } - contracts.l2SharedBridgeProxyBytecode = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json" + contracts.l2SharedBridgeProxyBytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json" ); - contracts.consensusRegistryBytecode = Utils.readHardhatBytecode( + contracts.consensusRegistryBytecode = Utils.readFoundryBytecode( "/../l2-contracts/zkout/ConsensusRegistry.sol/ConsensusRegistry.json" ); - contracts.consensusRegistryProxyBytecode = Utils.readHardhatBytecode( + contracts.consensusRegistryProxyBytecode = Utils.readFoundryBytecode( "/../l2-contracts/zkout/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json" ); - contracts.forceDeployUpgrader = Utils.readHardhatBytecode( + contracts.multicall3Bytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/Multicall3.sol/Multicall3.json" + ); + + contracts.forceDeployUpgrader = Utils.readFoundryBytecode( "/../l2-contracts/zkout/ForceDeployUpgrader.sol/ForceDeployUpgrader.json" ); + + contracts.timestampAsserterBytecode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/TimestampAsserter.sol/TimestampAsserter.json" + ); } function initializeConfig() internal { @@ -163,6 +193,8 @@ contract DeployL2Script is Script { vm.serializeAddress("root", "l2_shared_bridge_proxy", config.l2SharedBridgeProxy); vm.serializeAddress("root", "consensus_registry_implementation", config.consensusRegistryImplementation); vm.serializeAddress("root", "consensus_registry_proxy", config.consensusRegistryProxy); + vm.serializeAddress("root", "multicall3", config.multicall3); + vm.serializeAddress("root", "timestamp_asserter", config.timestampAsserter); string memory toml = vm.serializeAddress("root", "l2_default_upgrader", config.forceDeployUpgraderAddress); string memory root = vm.projectRoot(); string memory path = string.concat(root, "/script-out/output-deploy-l2-contracts.toml"); @@ -264,6 +296,35 @@ contract DeployL2Script is Script { }); } + function deployMulticall3() internal { + // Multicall3 doesn't have a constructor. + bytes memory constructorData = ""; + + config.multicall3 = Utils.deployThroughL1({ + bytecode: contracts.multicall3Bytecode, + constructorargs: constructorData, + create2salt: "", + l2GasLimit: Utils.MAX_PRIORITY_TX_GAS, + factoryDeps: new bytes[](0), + chainId: config.chainId, + bridgehubAddress: config.bridgehubAddress, + l1SharedBridgeProxy: config.l1SharedBridgeProxy + }); + } + + function deployTimestampAsserter() internal { + config.timestampAsserter = Utils.deployThroughL1({ + bytecode: contracts.timestampAsserterBytecode, + constructorargs: hex"", + create2salt: "", + l2GasLimit: Utils.MAX_PRIORITY_TX_GAS, + factoryDeps: new bytes[](0), + chainId: config.chainId, + bridgehubAddress: config.bridgehubAddress, + l1SharedBridgeProxy: config.l1SharedBridgeProxy + }); + } + // Deploy a transparent upgradable proxy for the already deployed consensus registry // implementation and save its address into the config. function deployConsensusRegistryProxy() internal { @@ -298,13 +359,11 @@ contract DeployL2Script is Script { function initializeChain() internal { L1SharedBridge bridge = L1SharedBridge(config.l1SharedBridgeProxy); - Utils.executeUpgrade({ - _governor: bridge.owner(), - _salt: bytes32(0), + Utils.chainAdminMulticall({ + _chainAdmin: bridge.admin(), _target: config.l1SharedBridgeProxy, _data: abi.encodeCall(bridge.initializeChainGovernance, (config.chainId, config.l2SharedBridgeProxy)), - _value: 0, - _delay: 0 + _value: 0 }); } } diff --git a/l1-contracts/deploy-scripts/EIP712Utils.sol b/l1-contracts/deploy-scripts/EIP712Utils.sol new file mode 100644 index 000000000..5f1aeb958 --- /dev/null +++ b/l1-contracts/deploy-scripts/EIP712Utils.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +library EIP712Utils { + bytes32 private constant TYPE_HASH = + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); + + function buildDomainHash( + address _verifyingContract, + string memory _name, + string memory _version + ) internal view returns (bytes32) { + return + keccak256( + // solhint-disable-next-line func-named-parameters + abi.encode( + TYPE_HASH, + keccak256(bytes(_name)), + keccak256(bytes(_version)), + block.chainid, + _verifyingContract + ) + ); + } + + function buildDigest(bytes32 _domainHash, bytes32 _message) internal view returns (bytes32) { + return keccak256(abi.encodePacked("\x19\x01", _domainHash, _message)); + } +} diff --git a/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol b/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol index 0e77cfe0d..a965704b6 100644 --- a/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol +++ b/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol @@ -14,6 +14,8 @@ import {L1SharedBridge} from "contracts/bridge/L1SharedBridge.sol"; import {IStateTransitionManager} from "contracts/state-transition/IStateTransitionManager.sol"; import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {IGovernance} from "contracts/governance/IGovernance.sol"; +import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; +import {Call} from "contracts/governance/Common.sol"; import {Utils} from "./Utils.sol"; /** @@ -109,24 +111,24 @@ contract PrepareZKChainRegistrationCalldataScript is Script { checkBaseTokenAddress(); - IGovernance.Call[] memory calls; + Call[] memory calls; uint256 cnt = 0; if (!IBridgehub(ecosystem.bridgehub).tokenIsRegistered(config.baseToken)) { - calls = new IGovernance.Call[](2); + calls = new Call[](2); console.log("Adding a call to register base token on the bridgehub"); - IGovernance.Call memory baseTokenRegistrationCall = prepareRegisterBaseTokenCall(); + Call memory baseTokenRegistrationCall = prepareRegisterBaseTokenCall(); calls[cnt] = baseTokenRegistrationCall; ++cnt; } else { - calls = new IGovernance.Call[](1); + calls = new Call[](1); } - IGovernance.Call memory registerChainCall = prepareRegisterHyperchainCall(); + Call memory registerChainCall = prepareRegisterHyperchainCall(); calls[cnt] = registerChainCall; ++cnt; address l2SharedBridgeProxy = computeL2BridgeAddress(); - IGovernance.Call memory initChainCall = prepareInitializeChainGovernanceCall(l2SharedBridgeProxy); + Call memory initChainCall = prepareInitializeChainGovernanceCall(l2SharedBridgeProxy); scheduleTransparentCalldata(calls, initChainCall); } @@ -182,12 +184,12 @@ contract PrepareZKChainRegistrationCalldataScript is Script { console.log("Using base token address:", config.baseToken); } - function prepareRegisterBaseTokenCall() internal view returns (IGovernance.Call memory) { + function prepareRegisterBaseTokenCall() internal view returns (Call memory) { Bridgehub bridgehub = Bridgehub(ecosystem.bridgehub); bytes memory data = abi.encodeCall(bridgehub.addToken, (config.baseToken)); - return IGovernance.Call({target: ecosystem.bridgehub, value: 0, data: data}); + return Call({target: ecosystem.bridgehub, value: 0, data: data}); } // @dev Computes the address of the L2 bridge and the L2 bridge proxy @@ -271,7 +273,7 @@ contract PrepareZKChainRegistrationCalldataScript is Script { return proxyContractAddress; } - function prepareRegisterHyperchainCall() internal view returns (IGovernance.Call memory) { + function prepareRegisterHyperchainCall() internal view returns (Call memory) { Bridgehub bridgehub = Bridgehub(ecosystem.bridgehub); AllowedBytecodeTypes allowedBytecodeTypesMode = config.allowEvmEmulator @@ -292,26 +294,21 @@ contract PrepareZKChainRegistrationCalldataScript is Script { ) ); - return IGovernance.Call({target: ecosystem.bridgehub, value: 0, data: data}); + return Call({target: ecosystem.bridgehub, value: 0, data: data}); } - function prepareInitializeChainGovernanceCall( - address l2SharedBridgeProxy - ) internal view returns (IGovernance.Call memory) { + function prepareInitializeChainGovernanceCall(address l2SharedBridgeProxy) internal view returns (Call memory) { L1SharedBridge bridge = L1SharedBridge(ecosystem.l1SharedBridgeProxy); bytes memory data = abi.encodeCall(bridge.initializeChainGovernance, (config.chainId, l2SharedBridgeProxy)); - return IGovernance.Call({target: ecosystem.l1SharedBridgeProxy, value: 0, data: data}); + return Call({target: ecosystem.l1SharedBridgeProxy, value: 0, data: data}); } // @dev Prepares a call to schedule a transparent operation on the governance contract // `calls` is an array of calls that will be executed in the first stage (add a token to BH, create a new chain) // `initChainGovCall` is a call that will be executed in the second stage (register the L2 bridge on the L1 shared bridge) - function scheduleTransparentCalldata( - IGovernance.Call[] memory calls, - IGovernance.Call memory initChainGovCall - ) internal { + function scheduleTransparentCalldata(Call[] memory calls, Call memory initChainGovCall) internal { IGovernance governance = IGovernance(ecosystem.governance); IGovernance.Operation memory operation = IGovernance.Operation({ @@ -323,7 +320,7 @@ contract PrepareZKChainRegistrationCalldataScript is Script { bytes memory scheduleCalldata = abi.encodeCall(governance.scheduleTransparent, (operation, 0)); bytes memory executeCalldata = abi.encodeCall(governance.execute, (operation)); - IGovernance.Call[] memory initChainGovArray = new IGovernance.Call[](1); + Call[] memory initChainGovArray = new Call[](1); initChainGovArray[0] = initChainGovCall; IGovernance.Operation memory operation2 = IGovernance.Operation({ diff --git a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol index a10d71b1f..c622d28c0 100644 --- a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol +++ b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol @@ -7,14 +7,12 @@ import {Script, console2 as console} from "forge-std/Script.sol"; import {Vm} from "forge-std/Vm.sol"; import {stdToml} from "forge-std/StdToml.sol"; -import {Ownable} from "@openzeppelin/contracts-v4/access/Ownable.sol"; -import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; +import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol"; import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol"; import {Governance} from "contracts/governance/Governance.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; -import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; import {Utils} from "./Utils.sol"; import {PubdataPricingMode} from "contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol"; @@ -123,20 +121,17 @@ contract RegisterHyperchainScript is Script { } function registerTokenOnBridgehub() internal { - IBridgehub bridgehub = IBridgehub(config.bridgehub); - Ownable ownable = Ownable(config.bridgehub); + Bridgehub bridgehub = Bridgehub(config.bridgehub); if (bridgehub.tokenIsRegistered(config.baseToken)) { console.log("Token already registered on Bridgehub"); } else { bytes memory data = abi.encodeCall(bridgehub.addToken, (config.baseToken)); - Utils.executeUpgrade({ - _governor: ownable.owner(), - _salt: bytes32(config.bridgehubCreateNewChainSalt), + Utils.chainAdminMulticall({ + _chainAdmin: bridgehub.admin(), _target: config.bridgehub, _data: data, - _value: 0, - _delay: 0 + _value: 0 }); console.log("Token registered on Bridgehub"); } @@ -155,19 +150,12 @@ contract RegisterHyperchainScript is Script { function deployChainAdmin() internal { vm.broadcast(); - AccessControlRestriction restriction = new AccessControlRestriction(0, config.ownerAddress); - - address[] memory restrictions = new address[](1); - restrictions[0] = address(restriction); - - vm.broadcast(); - ChainAdmin chainAdmin = new ChainAdmin(restrictions); + ChainAdmin chainAdmin = new ChainAdmin(config.ownerAddress, address(0)); config.chainAdmin = address(chainAdmin); } function registerHyperchain() internal { - IBridgehub bridgehub = IBridgehub(config.bridgehub); - Ownable ownable = Ownable(config.bridgehub); + Bridgehub bridgehub = Bridgehub(config.bridgehub); AllowedBytecodeTypes allowedBytecodeTypesMode = config.allowEvmEmulator ? AllowedBytecodeTypes.EraVmAndEVM @@ -188,14 +176,7 @@ contract RegisterHyperchainScript is Script { ) ); - Utils.executeUpgrade({ - _governor: ownable.owner(), - _salt: bytes32(config.bridgehubCreateNewChainSalt), - _target: config.bridgehub, - _data: data, - _value: 0, - _delay: 0 - }); + Utils.chainAdminMulticall({_chainAdmin: bridgehub.admin(), _target: config.bridgehub, _data: data, _value: 0}); console.log("Hyperchain registered"); // Get new diamond proxy address from emitted events diff --git a/l1-contracts/deploy-scripts/Utils.sol b/l1-contracts/deploy-scripts/Utils.sol index dc96b32b2..24bd49607 100644 --- a/l1-contracts/deploy-scripts/Utils.sol +++ b/l1-contracts/deploy-scripts/Utils.sol @@ -13,6 +13,27 @@ import {IERC20} from "@openzeppelin/contracts-v4/token/ERC20/IERC20.sol"; import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA} from "contracts/common/Config.sol"; import {L2_DEPLOYER_SYSTEM_CONTRACT_ADDR} from "contracts/common/L2ContractAddresses.sol"; import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol"; +import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; +import {EIP712Utils} from "./EIP712Utils.sol"; +import {IProtocolUpgradeHandler} from "./interfaces/IProtocolUpgradeHandler.sol"; +import {IEmergencyUpgrageBoard} from "./interfaces/IEmergencyUpgrageBoard.sol"; +import {IMultisig} from "./interfaces/IMultisig.sol"; +import {ISafe} from "./interfaces/ISafe.sol"; + +/// @dev EIP-712 TypeHash for the emergency protocol upgrade execution approved by the guardians. +bytes32 constant EXECUTE_EMERGENCY_UPGRADE_GUARDIANS_TYPEHASH = keccak256( + "ExecuteEmergencyUpgradeGuardians(bytes32 id)" +); + +/// @dev EIP-712 TypeHash for the emergency protocol upgrade execution approved by the Security Council. +bytes32 constant EXECUTE_EMERGENCY_UPGRADE_SECURITY_COUNCIL_TYPEHASH = keccak256( + "ExecuteEmergencyUpgradeSecurityCouncil(bytes32 id)" +); + +/// @dev EIP-712 TypeHash for the emergency protocol upgrade execution approved by the ZK Foundation. +bytes32 constant EXECUTE_EMERGENCY_UPGRADE_ZK_FOUNDATION_TYPEHASH = keccak256( + "ExecuteEmergencyUpgradeZKFoundation(bytes32 id)" +); library Utils { // Cheatcodes address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D. @@ -300,6 +321,15 @@ library Utils { return bytecode; } + function chainAdminMulticall(address _chainAdmin, address _target, bytes memory _data, uint256 _value) internal { + IChainAdmin chainAdmin = IChainAdmin(_chainAdmin); + + IChainAdmin.Call[] memory calls = new IChainAdmin.Call[](1); + calls[0] = IChainAdmin.Call({target: _target, value: _value, data: _data}); + vm.broadcast(); + chainAdmin.multicall(calls, true); + } + function executeUpgrade( address _governor, bytes32 _salt, @@ -326,4 +356,117 @@ library Utils { } vm.stopBroadcast(); } + + function executeEmergencyProtocolUpgrade( + IProtocolUpgradeHandler _protocolUpgradeHandler, + Vm.Wallet memory _governorWallet, + IProtocolUpgradeHandler.Call[] memory _calls, + bytes32 _salt + ) internal returns (bytes memory) { + bytes32 upgradeId; + bytes32 emergencyUpgradeBoardDigest; + { + address emergencyUpgradeBoard = _protocolUpgradeHandler.emergencyUpgradeBoard(); + IProtocolUpgradeHandler.UpgradeProposal memory upgradeProposal = IProtocolUpgradeHandler.UpgradeProposal({ + calls: _calls, + salt: _salt, + executor: emergencyUpgradeBoard + }); + upgradeId = keccak256(abi.encode(upgradeProposal)); + emergencyUpgradeBoardDigest = EIP712Utils.buildDomainHash( + emergencyUpgradeBoard, + "EmergencyUpgradeBoard", + "1" + ); + } + + bytes memory guardiansSignatures; + { + address[] memory guardiansMembers = new address[](8); + { + IMultisig guardians = IMultisig(_protocolUpgradeHandler.guardians()); + for (uint256 i = 0; i < 8; i++) { + guardiansMembers[i] = guardians.members(i); + } + } + bytes[] memory guardiansRawSignatures = new bytes[](8); + for (uint256 i = 0; i < 8; i++) { + bytes32 safeDigest; + { + bytes32 guardiansDigest = EIP712Utils.buildDigest( + emergencyUpgradeBoardDigest, + keccak256(abi.encode(EXECUTE_EMERGENCY_UPGRADE_GUARDIANS_TYPEHASH, upgradeId)) + ); + safeDigest = ISafe(guardiansMembers[i]).getMessageHash(abi.encode(guardiansDigest)); + } + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(_governorWallet, safeDigest); + guardiansRawSignatures[i] = abi.encodePacked(r, s, v); + } + guardiansSignatures = abi.encode(guardiansMembers, guardiansRawSignatures); + } + + bytes memory securityCouncilSignatures; + { + address[] memory securityCouncilMembers = new address[](12); + { + IMultisig securityCouncil = IMultisig(_protocolUpgradeHandler.securityCouncil()); + for (uint256 i = 0; i < 12; i++) { + securityCouncilMembers[i] = securityCouncil.members(i); + } + } + bytes[] memory securityCouncilRawSignatures = new bytes[](12); + for (uint256 i = 0; i < securityCouncilMembers.length; i++) { + bytes32 safeDigest; + { + bytes32 securityCouncilDigest = EIP712Utils.buildDigest( + emergencyUpgradeBoardDigest, + keccak256(abi.encode(EXECUTE_EMERGENCY_UPGRADE_SECURITY_COUNCIL_TYPEHASH, upgradeId)) + ); + safeDigest = ISafe(securityCouncilMembers[i]).getMessageHash(abi.encode(securityCouncilDigest)); + } + { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(_governorWallet, safeDigest); + securityCouncilRawSignatures[i] = abi.encodePacked(r, s, v); + } + } + securityCouncilSignatures = abi.encode(securityCouncilMembers, securityCouncilRawSignatures); + } + + bytes memory zkFoundationSignature; + { + ISafe zkFoundation; + { + IEmergencyUpgrageBoard emergencyUpgradeBoard = IEmergencyUpgrageBoard( + _protocolUpgradeHandler.emergencyUpgradeBoard() + ); + zkFoundation = ISafe(emergencyUpgradeBoard.ZK_FOUNDATION_SAFE()); + } + bytes32 zkFoundationDigest = EIP712Utils.buildDigest( + emergencyUpgradeBoardDigest, + keccak256(abi.encode(EXECUTE_EMERGENCY_UPGRADE_ZK_FOUNDATION_TYPEHASH, upgradeId)) + ); + bytes32 safeDigest = ISafe(zkFoundation).getMessageHash(abi.encode(zkFoundationDigest)); + { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(_governorWallet, safeDigest); + zkFoundationSignature = abi.encodePacked(r, s, v); + } + } + + { + vm.startBroadcast(); + IEmergencyUpgrageBoard emergencyUpgradeBoard = IEmergencyUpgrageBoard( + _protocolUpgradeHandler.emergencyUpgradeBoard() + ); + // solhint-disable-next-line func-named-parameters + emergencyUpgradeBoard.executeEmergencyUpgrade( + _calls, + _salt, + guardiansSignatures, + securityCouncilSignatures, + zkFoundationSignature + ); + vm.stopBroadcast(); + } + } } diff --git a/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol index 0f2e589f3..518005915 100644 --- a/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol +++ b/l1-contracts/deploy-scripts/dev/SetupLegacyBridge.s.sol @@ -104,6 +104,7 @@ contract SetupLegacyBridge is Script { function setParamsForDummyBridge() internal { (address l2TokenBeacon, bytes32 l2TokenBeaconHash) = calculateTokenBeaconAddress(); DummyL1ERC20Bridge bridge = DummyL1ERC20Bridge(addresses.erc20BridgeProxy); + vm.broadcast(); bridge.setValues(config.l2SharedBridgeAddress, l2TokenBeacon, l2TokenBeaconHash); } @@ -111,8 +112,8 @@ contract SetupLegacyBridge is Script { internal returns (address tokenBeaconAddress, bytes32 tokenBeaconBytecodeHash) { - bytes memory l2StandardTokenCode = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/contracts/bridge/L2StandardERC20.sol/L2StandardERC20.json" + bytes memory l2StandardTokenCode = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/L2StandardERC20.sol/L2StandardERC20.json" ); (address l2StandardToken, ) = calculateL2Create2Address( config.l2SharedBridgeAddress, @@ -121,13 +122,16 @@ contract SetupLegacyBridge is Script { "" ); - bytes memory beaconProxy = Utils.readHardhatBytecode( - "/../l2-contracts/artifacts-zk/@openzeppelin/contracts-v4/proxy/beacon/BeaconProxy.sol/BeaconProxy.json" + bytes memory beaconProxy = Utils.readFoundryBytecode("/../l2-contracts/zkout/BeaconProxy.sol/BeaconProxy.json"); + tokenBeaconBytecodeHash = L2ContractHelper.hashL2Bytecode(beaconProxy); + + bytes memory upgradableBeacon = Utils.readFoundryBytecode( + "/../l2-contracts/zkout/UpgradeableBeacon.sol/UpgradeableBeacon.json" ); - (tokenBeaconAddress, tokenBeaconBytecodeHash) = calculateL2Create2Address( + (tokenBeaconAddress, ) = calculateL2Create2Address( config.l2SharedBridgeAddress, - beaconProxy, + upgradableBeacon, bytes32(0), abi.encode(l2StandardToken) ); diff --git a/l1-contracts/deploy-scripts/interfaces/IEmergencyUpgrageBoard.sol b/l1-contracts/deploy-scripts/interfaces/IEmergencyUpgrageBoard.sol new file mode 100644 index 000000000..1f3d0d3d6 --- /dev/null +++ b/l1-contracts/deploy-scripts/interfaces/IEmergencyUpgrageBoard.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {IProtocolUpgradeHandler} from "./IProtocolUpgradeHandler.sol"; + +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +interface IEmergencyUpgrageBoard { + function GUARDIANS() external view returns (address); + + function SECURITY_COUNCIL() external view returns (address); + + function ZK_FOUNDATION_SAFE() external view returns (address); + + function executeEmergencyUpgrade( + IProtocolUpgradeHandler.Call[] calldata _calls, + bytes32 _salt, + bytes calldata _guardiansSignatures, + bytes calldata _securityCouncilSignatures, + bytes calldata _zkFoundationSignatures + ) external; +} diff --git a/l1-contracts/deploy-scripts/interfaces/IMultisig.sol b/l1-contracts/deploy-scripts/interfaces/IMultisig.sol new file mode 100644 index 000000000..2a1dd955d --- /dev/null +++ b/l1-contracts/deploy-scripts/interfaces/IMultisig.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +interface IMultisig { + function members(uint256) external view returns (address); +} diff --git a/l1-contracts/deploy-scripts/interfaces/IProtocolUpgradeHandler.sol b/l1-contracts/deploy-scripts/interfaces/IProtocolUpgradeHandler.sol new file mode 100644 index 000000000..baa48f43f --- /dev/null +++ b/l1-contracts/deploy-scripts/interfaces/IProtocolUpgradeHandler.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +interface IProtocolUpgradeHandler { + /// @dev Represents a call to be made during an upgrade. + /// @param target The address to which the call will be made. + /// @param value The amount of Ether (in wei) to be sent along with the call. + /// @param data The calldata to be executed on the `target` address. + struct Call { + address target; + uint256 value; + bytes data; + } + + /// @dev Defines the structure of an upgrade that is executed by Protocol Upgrade Handler. + /// @param executor The L1 address that is authorized to perform the upgrade execution (if address(0) then anyone). + /// @param calls An array of `Call` structs, each representing a call to be made during the upgrade execution. + /// @param salt A bytes32 value used for creating unique upgrade proposal hashes. + struct UpgradeProposal { + Call[] calls; + address executor; + bytes32 salt; + } + + function emergencyUpgradeBoard() external view returns (address); + + function guardians() external view returns (address); + + function securityCouncil() external view returns (address); +} diff --git a/l1-contracts/deploy-scripts/interfaces/ISafe.sol b/l1-contracts/deploy-scripts/interfaces/ISafe.sol new file mode 100644 index 000000000..82877b3b3 --- /dev/null +++ b/l1-contracts/deploy-scripts/interfaces/ISafe.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +interface ISafe { + function getMessageHash(bytes memory _message) external view returns (bytes32); +} diff --git a/l1-contracts/script-config/.gitkeep b/l1-contracts/script-config/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/l1-contracts/script-config/artifacts/BeaconProxy.json b/l1-contracts/script-config/artifacts/BeaconProxy.json deleted file mode 100644 index 258780377..000000000 --- a/l1-contracts/script-config/artifacts/BeaconProxy.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "_format": "hh-zksolc-artifact-1", - "contractName": "BeaconProxy", - "sourceName": "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "beacon", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "bytecode": "0x0004000000000002000700000000000200000000030100190000006003300270000001020030019d0000010203300197000300000031035500020000000103550000008008000039000000400080043f00000001022001900000001c0000c13d000000000131034f0000010d02000041000000000202041a0000010b04000041000000800040043f00000106022001970000000004000414000000000303004b000000250000c13d000000040320008c000000ab0000c13d0000000103000031000000200230008c00000000040300190000002004008039000000d60000013d0000010302300041000001040220009c0000002c0000213d0000011d0100004100000000001004350000004101000039000000040010043f0000011e010000410000040400010430000000040320008c000001160000c13d0000000103000031000000200230008c00000000040300190000002004008039000001410000013d0000009f023000390000010502200197000000400020043f0000001f0230018f00000005043002720000003b0000613d00000000050000190000000506500210000000000761034f000000000707043b000000800660003900000000007604350000000105500039000000000645004b000000330000413d000000000502004b0000004a0000613d0000000504400210000000000141034f00000003022002100000008004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f00000000001404350000003f0130008c0000014a0000a13d000000800a00043d0000010601a0009c0000014a0000213d000000a00200043d000001070120009c0000014a0000213d0000001f012000390000010804000041000000000531004b000000000500001900000000050480190000010801100197000000000601004b0000000004008019000001080110009c000000000405c019000000000104004b0000014a0000c13d00000080012000390000000001010433000001070410009c0000001f0000213d0000003f04100039000000200700008a000000000474016f000000400900043d0000000004490019000000000594004b00000000050000190000000105004039000001070640009c0000001f0000213d00000001055001900000001f0000c13d0000008003300039000000400040043f0000000006190436000000a0022000390000000004210019000000000334004b0000014a0000213d000600000009001d000500000007001d000400000008001d000000000301004b000000820000613d000000000300001900000000046300190000000005230019000000000505043300000000005404350000002003300039000000000413004b0000007b0000413d000300000006001d000000000116001900000000000104350000010901000041000000000010043900070000000a001d0000000400a0044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000400a00043d000000000101043b000000000101004b000002200000c13d0000006401a000390000011b0200004100000000002104350000004401a000390000011c0200004100000000002104350000002401a0003900000025020000390000000000210435000001150100004100000000001a04350000000401a000390000002002000039000000000021043500000102010000410000010202a0009c000000000a0180190000004001a002100000011a011001c700000404000104300000010201000041000001020340009c0000000004018019000000c0014002100000011f011001c7040203f80000040f000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000000c30000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000000bb0000413d000000000705004b000000d20000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f000300000001035500000001022001900000014c0000613d0000009f02400039000000e00220018f000000400020043f000000200230008c0000014a0000413d000000800200043d000001060420009c0000014a0000213d000000020500036700000000040000310000001f0740018f0000000506400272000000eb0000613d00000000080000190000000509800210000000000a95034f000000000a0a043b0000000000a904350000000108800039000000000968004b000000e40000413d000000000807004b000000f90000613d00000003077002100000000506600210000000000806043300000000087801cf000000000878022f000000000565034f000000000505043b0000010007700089000000000575022f00000000057501cf000000000585019f00000000005604350000000005000414000000040620008c000001c40000c13d0000001f0430018f0000000502300272000001070000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b000001000000413d000000000504004b000001ed0000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000001ed0000013d0000010201000041000001020340009c0000000004018019000000c0014002100000011f011001c7040203f80000040f000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f00000005064002720000012e0000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000001260000413d000000000705004b0000013d0000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000001690000613d0000001f02400039000000600220018f00000080022001bf000000400020043f000000200230008c0000014a0000413d000000800200043d000001060420009c0000018c0000a13d00000000010000190000040400010430000000400200043d0000001f0430018f0000000505300272000001590000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000001510000413d000000000604004b000001680000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d000000400200043d0000001f0430018f0000000505300272000001760000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000016e0000413d000000000604004b000001850000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000010201000041000001020420009c000000000201801900000040012002100000006002300210000000000121019f0000040400010430000000020500036700000000040000310000001f0740018f0000000506400272000001990000613d00000000080000190000000509800210000000000a95034f000000000a0a043b0000000000a904350000000108800039000000000968004b000001920000413d000000000807004b000001a70000613d00000003077002100000000506600210000000000806043300000000087801cf000000000878022f000000000565034f000000000505043b0000010007700089000000000575022f00000000057501cf000000000585019f00000000005604350000000005000414000000040620008c000001ee0000c13d0000001f0430018f0000000502300272000001b50000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b000001ae0000413d000000000504004b000002170000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000002170000013d0000010201000041000001020350009c0000000005018019000001020340009c00000000040180190000006001400210000000c003500210000000000113019f040203fd0000040f0003000000010355000000000301001900000060033002700000001f0430018f000101020030019d00000102033001970000000505300272000001dd0000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000001d60000413d000000000604004b000001eb0000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000001012001900000021c0000613d000002170000013d0000010201000041000001020350009c0000000005018019000001020340009c00000000040180190000006001400210000000c003500210000000000113019f040203fd0000040f0003000000010355000000000301001900000060033002700000001f0430018f000101020030019d00000102033001970000000505300272000002070000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000002000000413d000000000604004b000002150000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000001012001900000021e0000613d0000010201000041000001020230009c00000000030180190000006001300210000004030001042e00000060013002100000040400010430000000600130021000000404000104300000010b0100004100000000001a0435000000000100041400000007020000290000010602200197000000040320008c000700000002001d0000022d0000c13d0000000103000031000000200130008c000000000403001900000020040080390000025e0000013d0000010204000041000001020310009c00000000010480190000010203a0009c00000000040a40190000004003400210000000c001100210000000000131019f0000010c011001c700020000000a001d040203f80000040f000000020a000029000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f00000005064002720000024b0000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000002430000413d000000000705004b0000025a0000613d0000000506600210000000000761034f00000000066a00190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000002950000613d0000001f01400039000000600210018f0000000001a20019000000000221004b00000000020000190000000102004039000001070410009c0000001f0000213d00000001022001900000001f0000c13d000000400010043f000000200130008c0000014a0000413d00000000010a0433000001060210009c0000014a0000213d00000109020000410000000000200439000000040010044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000400200043d000200000002001d000000000101043b000000000101004b000002b20000c13d0000000203000029000000640130003900000118020000410000000000210435000000440130003900000119020000410000000000210435000000240130003900000030020000390000000000210435000001150100004100000000001304350000000401300039000000200200003900000000002104350000010201000041000001020230009c000000000301801900000040013002100000011a011001c70000040400010430000000400200043d0000001f0430018f0000000505300272000002a20000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000029a0000413d000000000604004b000001850000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d0000010d01000041000000000201041a0000010e022001970000000705000029000000000252019f000000000021041b00000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010f011001c70000800d0200003900000002030000390000011004000041040203f30000040f000000010120019000000006010000290000014a0000613d0000000001010433000000000101004b000002cd0000c13d0000002001000039000001000010044300000120000004430000011701000041000004030001042e0000010b010000410000000202000029000000000012043500000000010004140000000702000029000000040220008c000002d90000c13d0000000103000031000000200130008c000000000403001900000020040080390000030b0000013d0000010202000041000001020310009c00000000010280190000000204000029000001020340009c00000000020440190000004002200210000000c001100210000000000121019f0000010c011001c70000000702000029040203f80000040f000000020a000029000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000002f80000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000002f00000413d000000000705004b000003070000613d0000000506600210000000000761034f00000002066000290000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000003380000613d0000001f01400039000000600110018f0000000202100029000000000112004b00000000010000190000000101004039000700000002001d000001070220009c00000006040000290000001f0000213d00000001011001900000001f0000c13d0000000701000029000000400010043f000000200130008c0000014a0000413d00000002010000290000000001010433000200000001001d000001060110009c0000014a0000213d0000000701000029000001110110009c0000001f0000213d00000007050000290000006001500039000000400010043f000000400150003900000112020000410000000000210435000000270100003900000000021504360000011301000041000100000002001d0000000000120435000000000204043300000000010004140000000204000029000000040440008c000003550000c13d0000000102000039000001070130009c00000005050000290000001f0000213d0000036d0000013d000000400200043d0000001f0430018f0000000505300272000003450000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000033d0000413d000000000604004b000003540000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d00000102030000410000000305000029000001020450009c00000000050380190000004004500210000001020520009c00000000020380190000006002200210000000000242019f000001020410009c0000000001038019000000c001100210000000000121019f0000000202000029040203fd0000040f0000006004000039000000010220018f00030000000103550000006001100270000101020010019d000001020310019800000004090000290000000505000029000003960000613d0000003f01300039000000000151016f000000400400043d0000000001140019000000000541004b00000000050000190000000105004039000001070610009c0000001f0000213d00000001055001900000001f0000c13d000000400010043f0000001f0130018f000000000934043600000003050003670000000503300272000003870000613d000000000600001900000005076002100000000008790019000000000775034f000000000707043b00000000007804350000000106600039000000000736004b0000037f0000413d000000000601004b000003960000613d0000000503300210000000000535034f00000000033900190000000301100210000000000603043300000000061601cf000000000616022f000000000505043b0000010001100089000000000515022f00000000011501cf000000000161019f00000000001304350000000001040433000000000202004b000003b60000c13d000000000201004b000003dc0000c13d000000400400043d000600000004001d0000011501000041000000000014043500000004014000390000002002000039000000000021043500000007010000290000000003010433000700000003001d0000002401400039000000000031043500000044024000390000000101000029040203e50000040f00000007010000290000001f01100039000000050110017f00000044011000390000010202000041000001020310009c00000000010280190000000604000029000001020340009c00000000040280190000004002400210000003e20000013d000000000101004b000002c80000c13d000001090100004100000000001004390000000201000029000000040010044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000000101043b000000000101004b000002c80000c13d000000400100043d00000044021000390000011403000041000000000032043500000024021000390000001d030000390000000000320435000001150200004100000000002104350000000402100039000000200300003900000000003204350000010202000041000001020310009c0000000001028019000000400110021000000116011001c70000040400010430000000000001042f0000010202000041000001020310009c0000000001028019000001020390009c000000000902801900000040029002100000006001100210000000000121019f0000040400010430000000000403004b000003ef0000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000534004b000003e80000413d00000000012300190000000000010435000000000001042d000000000001042f000003f6002104210000000102000039000000000001042d0000000002000019000000000001042d000003fb002104230000000102000039000000000001042d0000000002000019000000000001042d00000400002104250000000102000039000000000001042d0000000002000019000000000001042d0000040200000432000004030001042e000004040001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009fffffffffffffffffffffffffffffffffffffffffffffffff000000000000007f00000000000000000000000000000000000000000000000000000001ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff80000000000000000000000000000000000000000000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8302000002000000000000000000000000000000240000000000000000000000005c60da1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000a3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50ffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e000000000000000000000000000000000000000000000000ffffffffffffff9f206661696c656400000000000000000000000000000000000000000000000000416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000008c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000020000000000000000000000000000004000000100000000000000000073206e6f74206120636f6e747261637400000000000000000000000000000000455243313936373a20626561636f6e20696d706c656d656e746174696f6e206900000000000000000000000000000000000000840000000000000000000000007472616374000000000000000000000000000000000000000000000000000000455243313936373a206e657720626561636f6e206973206e6f74206120636f6e4e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000004000000800000000000000000d32177e88b033622e0bc848f24ab73d0795ed87730981120fcdf94fbc134fa5d", - "deployedBytecode": "0x0004000000000002000700000000000200000000030100190000006003300270000001020030019d0000010203300197000300000031035500020000000103550000008008000039000000400080043f00000001022001900000001c0000c13d000000000131034f0000010d02000041000000000202041a0000010b04000041000000800040043f00000106022001970000000004000414000000000303004b000000250000c13d000000040320008c000000ab0000c13d0000000103000031000000200230008c00000000040300190000002004008039000000d60000013d0000010302300041000001040220009c0000002c0000213d0000011d0100004100000000001004350000004101000039000000040010043f0000011e010000410000040400010430000000040320008c000001160000c13d0000000103000031000000200230008c00000000040300190000002004008039000001410000013d0000009f023000390000010502200197000000400020043f0000001f0230018f00000005043002720000003b0000613d00000000050000190000000506500210000000000761034f000000000707043b000000800660003900000000007604350000000105500039000000000645004b000000330000413d000000000502004b0000004a0000613d0000000504400210000000000141034f00000003022002100000008004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f00000000001404350000003f0130008c0000014a0000a13d000000800a00043d0000010601a0009c0000014a0000213d000000a00200043d000001070120009c0000014a0000213d0000001f012000390000010804000041000000000531004b000000000500001900000000050480190000010801100197000000000601004b0000000004008019000001080110009c000000000405c019000000000104004b0000014a0000c13d00000080012000390000000001010433000001070410009c0000001f0000213d0000003f04100039000000200700008a000000000474016f000000400900043d0000000004490019000000000594004b00000000050000190000000105004039000001070640009c0000001f0000213d00000001055001900000001f0000c13d0000008003300039000000400040043f0000000006190436000000a0022000390000000004210019000000000334004b0000014a0000213d000600000009001d000500000007001d000400000008001d000000000301004b000000820000613d000000000300001900000000046300190000000005230019000000000505043300000000005404350000002003300039000000000413004b0000007b0000413d000300000006001d000000000116001900000000000104350000010901000041000000000010043900070000000a001d0000000400a0044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000400a00043d000000000101043b000000000101004b000002200000c13d0000006401a000390000011b0200004100000000002104350000004401a000390000011c0200004100000000002104350000002401a0003900000025020000390000000000210435000001150100004100000000001a04350000000401a000390000002002000039000000000021043500000102010000410000010202a0009c000000000a0180190000004001a002100000011a011001c700000404000104300000010201000041000001020340009c0000000004018019000000c0014002100000011f011001c7040203f80000040f000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000000c30000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000000bb0000413d000000000705004b000000d20000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f000300000001035500000001022001900000014c0000613d0000009f02400039000000e00220018f000000400020043f000000200230008c0000014a0000413d000000800200043d000001060420009c0000014a0000213d000000020500036700000000040000310000001f0740018f0000000506400272000000eb0000613d00000000080000190000000509800210000000000a95034f000000000a0a043b0000000000a904350000000108800039000000000968004b000000e40000413d000000000807004b000000f90000613d00000003077002100000000506600210000000000806043300000000087801cf000000000878022f000000000565034f000000000505043b0000010007700089000000000575022f00000000057501cf000000000585019f00000000005604350000000005000414000000040620008c000001c40000c13d0000001f0430018f0000000502300272000001070000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b000001000000413d000000000504004b000001ed0000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000001ed0000013d0000010201000041000001020340009c0000000004018019000000c0014002100000011f011001c7040203f80000040f000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f00000005064002720000012e0000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000001260000413d000000000705004b0000013d0000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000001690000613d0000001f02400039000000600220018f00000080022001bf000000400020043f000000200230008c0000014a0000413d000000800200043d000001060420009c0000018c0000a13d00000000010000190000040400010430000000400200043d0000001f0430018f0000000505300272000001590000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000001510000413d000000000604004b000001680000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d000000400200043d0000001f0430018f0000000505300272000001760000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000016e0000413d000000000604004b000001850000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000010201000041000001020420009c000000000201801900000040012002100000006002300210000000000121019f0000040400010430000000020500036700000000040000310000001f0740018f0000000506400272000001990000613d00000000080000190000000509800210000000000a95034f000000000a0a043b0000000000a904350000000108800039000000000968004b000001920000413d000000000807004b000001a70000613d00000003077002100000000506600210000000000806043300000000087801cf000000000878022f000000000565034f000000000505043b0000010007700089000000000575022f00000000057501cf000000000585019f00000000005604350000000005000414000000040620008c000001ee0000c13d0000001f0430018f0000000502300272000001b50000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b000001ae0000413d000000000504004b000002170000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000002170000013d0000010201000041000001020350009c0000000005018019000001020340009c00000000040180190000006001400210000000c003500210000000000113019f040203fd0000040f0003000000010355000000000301001900000060033002700000001f0430018f000101020030019d00000102033001970000000505300272000001dd0000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000001d60000413d000000000604004b000001eb0000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000001012001900000021c0000613d000002170000013d0000010201000041000001020350009c0000000005018019000001020340009c00000000040180190000006001400210000000c003500210000000000113019f040203fd0000040f0003000000010355000000000301001900000060033002700000001f0430018f000101020030019d00000102033001970000000505300272000002070000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000002000000413d000000000604004b000002150000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000001012001900000021e0000613d0000010201000041000001020230009c00000000030180190000006001300210000004030001042e00000060013002100000040400010430000000600130021000000404000104300000010b0100004100000000001a0435000000000100041400000007020000290000010602200197000000040320008c000700000002001d0000022d0000c13d0000000103000031000000200130008c000000000403001900000020040080390000025e0000013d0000010204000041000001020310009c00000000010480190000010203a0009c00000000040a40190000004003400210000000c001100210000000000131019f0000010c011001c700020000000a001d040203f80000040f000000020a000029000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f00000005064002720000024b0000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000002430000413d000000000705004b0000025a0000613d0000000506600210000000000761034f00000000066a00190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000002950000613d0000001f01400039000000600210018f0000000001a20019000000000221004b00000000020000190000000102004039000001070410009c0000001f0000213d00000001022001900000001f0000c13d000000400010043f000000200130008c0000014a0000413d00000000010a0433000001060210009c0000014a0000213d00000109020000410000000000200439000000040010044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000400200043d000200000002001d000000000101043b000000000101004b000002b20000c13d0000000203000029000000640130003900000118020000410000000000210435000000440130003900000119020000410000000000210435000000240130003900000030020000390000000000210435000001150100004100000000001304350000000401300039000000200200003900000000002104350000010201000041000001020230009c000000000301801900000040013002100000011a011001c70000040400010430000000400200043d0000001f0430018f0000000505300272000002a20000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000029a0000413d000000000604004b000001850000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d0000010d01000041000000000201041a0000010e022001970000000705000029000000000252019f000000000021041b00000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010f011001c70000800d0200003900000002030000390000011004000041040203f30000040f000000010120019000000006010000290000014a0000613d0000000001010433000000000101004b000002cd0000c13d0000002001000039000001000010044300000120000004430000011701000041000004030001042e0000010b010000410000000202000029000000000012043500000000010004140000000702000029000000040220008c000002d90000c13d0000000103000031000000200130008c000000000403001900000020040080390000030b0000013d0000010202000041000001020310009c00000000010280190000000204000029000001020340009c00000000020440190000004002200210000000c001100210000000000121019f0000010c011001c70000000702000029040203f80000040f000000020a000029000000000301001900000060033002700000010203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000002f80000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000002f00000413d000000000705004b000003070000613d0000000506600210000000000761034f00000002066000290000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000003380000613d0000001f01400039000000600110018f0000000202100029000000000112004b00000000010000190000000101004039000700000002001d000001070220009c00000006040000290000001f0000213d00000001011001900000001f0000c13d0000000701000029000000400010043f000000200130008c0000014a0000413d00000002010000290000000001010433000200000001001d000001060110009c0000014a0000213d0000000701000029000001110110009c0000001f0000213d00000007050000290000006001500039000000400010043f000000400150003900000112020000410000000000210435000000270100003900000000021504360000011301000041000100000002001d0000000000120435000000000204043300000000010004140000000204000029000000040440008c000003550000c13d0000000102000039000001070130009c00000005050000290000001f0000213d0000036d0000013d000000400200043d0000001f0430018f0000000505300272000003450000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000033d0000413d000000000604004b000003540000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001850000013d00000102030000410000000305000029000001020450009c00000000050380190000004004500210000001020520009c00000000020380190000006002200210000000000242019f000001020410009c0000000001038019000000c001100210000000000121019f0000000202000029040203fd0000040f0000006004000039000000010220018f00030000000103550000006001100270000101020010019d000001020310019800000004090000290000000505000029000003960000613d0000003f01300039000000000151016f000000400400043d0000000001140019000000000541004b00000000050000190000000105004039000001070610009c0000001f0000213d00000001055001900000001f0000c13d000000400010043f0000001f0130018f000000000934043600000003050003670000000503300272000003870000613d000000000600001900000005076002100000000008790019000000000775034f000000000707043b00000000007804350000000106600039000000000736004b0000037f0000413d000000000601004b000003960000613d0000000503300210000000000535034f00000000033900190000000301100210000000000603043300000000061601cf000000000616022f000000000505043b0000010001100089000000000515022f00000000011501cf000000000161019f00000000001304350000000001040433000000000202004b000003b60000c13d000000000201004b000003dc0000c13d000000400400043d000600000004001d0000011501000041000000000014043500000004014000390000002002000039000000000021043500000007010000290000000003010433000700000003001d0000002401400039000000000031043500000044024000390000000101000029040203e50000040f00000007010000290000001f01100039000000050110017f00000044011000390000010202000041000001020310009c00000000010280190000000604000029000001020340009c00000000040280190000004002400210000003e20000013d000000000101004b000002c80000c13d000001090100004100000000001004390000000201000029000000040010044300000102010000410000000002000414000001020320009c0000000002018019000000c0012002100000010a011001c70000800202000039040203f80000040f0000000102200190000003db0000613d000000000101043b000000000101004b000002c80000c13d000000400100043d00000044021000390000011403000041000000000032043500000024021000390000001d030000390000000000320435000001150200004100000000002104350000000402100039000000200300003900000000003204350000010202000041000001020310009c0000000001028019000000400110021000000116011001c70000040400010430000000000001042f0000010202000041000001020310009c0000000001028019000001020390009c000000000902801900000040029002100000006001100210000000000121019f0000040400010430000000000403004b000003ef0000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000534004b000003e80000413d00000000012300190000000000010435000000000001042d000000000001042f000003f6002104210000000102000039000000000001042d0000000002000019000000000001042d000003fb002104230000000102000039000000000001042d0000000002000019000000000001042d00000400002104250000000102000039000000000001042d0000000002000019000000000001042d0000040200000432000004030001042e000004040001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009fffffffffffffffffffffffffffffffffffffffffffffffff000000000000007f00000000000000000000000000000000000000000000000000000001ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff80000000000000000000000000000000000000000000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8302000002000000000000000000000000000000240000000000000000000000005c60da1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000a3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50ffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e000000000000000000000000000000000000000000000000ffffffffffffff9f206661696c656400000000000000000000000000000000000000000000000000416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000008c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000020000000000000000000000000000004000000100000000000000000073206e6f74206120636f6e747261637400000000000000000000000000000000455243313936373a20626561636f6e20696d706c656d656e746174696f6e206900000000000000000000000000000000000000840000000000000000000000007472616374000000000000000000000000000000000000000000000000000000455243313936373a206e657720626561636f6e206973206e6f74206120636f6e4e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000004000000800000000000000000d32177e88b033622e0bc848f24ab73d0795ed87730981120fcdf94fbc134fa5d", - "linkReferences": {}, - "deployedLinkReferences": {}, - "factoryDeps": {} -} diff --git a/l1-contracts/script-config/artifacts/L2SharedBridge.json b/l1-contracts/script-config/artifacts/L2SharedBridge.json deleted file mode 100644 index a74e5c9ad..000000000 --- a/l1-contracts/script-config/artifacts/L2SharedBridge.json +++ /dev/null @@ -1,262 +0,0 @@ -{ - "_format": "hh-zksolc-artifact-1", - "contractName": "L2SharedBridge", - "sourceName": "contracts/bridge/L2SharedBridge.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_eraChainId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Receiver", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FinalizeDeposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l2Sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l1Receiver", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "l2Token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrawalInitiated", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Sender", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Receiver", - "type": "address" - }, - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "finalizeDeposit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1SharedBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "_l1Bridge", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_l2TokenProxyBytecodeHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_aliasedOwner", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Bridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1SharedBridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "l2TokenAddress", - "type": "address" - } - ], - "name": "l1TokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "l1TokenAddress", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - } - ], - "name": "l2TokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l2TokenBeacon", - "outputs": [ - { - "internalType": "contract UpgradeableBeacon", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Receiver", - "type": "address" - }, - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x0004000000000002001000000000000200000000030100190000006004300270000001a20340019700030000003103550002000000010355000001a20040019d00000001022001900000001d0000c13d0000008002000039000000400020043f000000040230008c000000400000413d000000000201043b000000e002200270000001ab0420009c000000420000213d000001b10420009c0000008a0000213d000001b40120009c000000c10000613d000001b50120009c000000400000c13d0000000001000416000000000101004b000000400000c13d0000000401000039000001d90000013d0000000002000416000000000202004b000000400000c13d000000bf02300039000001a302200197000000400020043f0000001f0230018f00000005043002720000002f0000613d00000000050000190000000506500210000000000761034f000000000707043b000000a00660003900000000007604350000000105500039000000000645004b000000270000413d000000000502004b0000003e0000613d0000000504400210000000000141034f0000000302200210000000a004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f0000000000140435000000200130008c000000640000813d00000000010000190000068300010430000001ac0420009c000000940000213d000001af0420009c000000c60000613d000001b00220009c000000400000c13d0000000002000416000000000202004b000000400000c13d000000040230008a000000600220008c000000400000413d0000000402100370000000000402043b000001b60240009c000000400000213d0000002402100370000000000302043b000001b60230009c000000400000213d0000004401100370000000000201043b000000000102004b000001de0000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000001501000039000000a40010043f000001c501000041000000c40010043f000001c6010000410000068300010430000000a00100043d000000800010043f000000000200041a0000ff0003200190000000ac0000c13d000000ff0320018f000000ff0330008c000000820000613d000000ff012001bf000000000010041b000000ff01000039000000400200043d0000000000120435000001a2010000410000000003000414000001a20430009c0000000003018019000001a20420009c00000000020180190000004001200210000000c002300210000000000112019f000001a8011001c70000800d020000390000000103000039000001a904000041068106770000040f0000000101200190000000400000613d000000800100043d000001400000044300000160001004430000002001000039000001000010044300000001010000390000012000100443000001aa01000041000006820001042e000001b20420009c000001a50000613d000001b30120009c000000400000c13d0000000001000416000000000101004b000000400000c13d000000000100041a0000001001100270000001da0000013d000001ad0420009c000001c90000613d000001ae0220009c000000400000c13d0000000002000416000000000202004b000000400000c13d000000040230008a000000200220008c000000400000413d0000000401100370000000000101043b000001b60210009c000000400000213d068106050000040f000001b601100197000000400200043d0000000000120435000001a201000041000001a20320009c00000000020180190000004001200210000001b7011001c7000006820001042e000000400100043d0000006402100039000001a40300004100000000003204350000004402100039000001a5030000410000000000320435000000240210003900000027030000390000000000320435000001a6020000410000000000210435000000040210003900000020030000390000000000320435000001a202000041000001a20310009c00000000010280190000004001100210000001a7011001c700000683000104300000000001000416000000000101004b000000400000c13d0000000101000039000001d90000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000a00220008c000000400000413d0000000402100370000000000802043b000001b60280009c000000400000213d0000002402100370000000000902043b000001b60290009c000000400000213d0000004402100370000000000a02043b000001b602a0009c000000400000213d0000008402100370000000000202043b000001bd0420009c000000400000213d0000002304200039000001c705000041000000000634004b00000000060000190000000006058019000001c704400197000000000704004b0000000005008019000001c70440009c000000000506c019000000000405004b000000400000c13d0000000404200039000000000441034f000000000504043b000001bd0450009c000000400000213d001000240020003d0000001002500029000000000232004b000000400000213d000b00000005001d000f0000000a001d000e00000009001d000c00000008001d0000006401100370000000000101043b000d00000001001d0000000001000411000001c801100041000001b6011001970000000402000039000000000202041a000001b602200197000000000221004b000001050000613d000000000200041a0000001002200270000001b602200197000000000121004b000002c10000c13d0000000101000039000800000001001d000000000101041a000001b601100197000000a00010043f0000004001000039000900000001001d000000c00010043f000000e00000043f0000006001000039000a00000001001d000000800010043f0000010001000039000000400010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ca011001c700008010020000390681067c0000040f00000001022001900000000f05000029000000400000613d0000000202000039000700000002001d000000000202041a000000000301043b000000400100043d000000a004100039000000000034043500000080031000390000000000230435000000600210003900000000005204350000004002100039000000000300041000000000003204350000002002100039000001cb030000410000000000320435000000a0030000390000000000310435000001cc0310009c000002170000213d000000c003100039000000400030043f000001a204000041000001a20320009c000000000204801900000040022002100000000001010433000001a20310009c00000000010480190000006001100210000000000121019f0000000002000414000001a20320009c0000000002048019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000000101043b000500000001001d000001b601100197000600000001001d00000000001004350000000301000039000400000001001d000000200010043f0000000001000414000001a20210009c000001a201008041000000c001100210000001be011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000000101043b000000000101041a000001b601100198000003ad0000c13d00000000010004140000000702000029000000000402041a0000000802000029000000000202041a000000400300043d000000400530003900000009060000290000000000650435000001b602200197000000200530003900000000002504350000000a02000029000000000023043500000060023000390000000000020435000001c00230009c000002170000213d0000008002300039000000400020043f000000a005300039000001cf060000410000000000650435000000e4053000390000000a060000290000000000650435000000c4053000390000000000450435000000a4043000390000000f0500002900000000005404350000010405300039000000000403043300000000004504350000012405300039000000000604004b0000018a0000613d000000000600001900000000075600190000002006600039000000000836001900000000080804330000000000870435000000000746004b000001830000413d000000000354001900000000000304350000001f03400039000a0020000000920000000a0330017f00000084043000390000000000420435000000c3033000390000000a0430017f0000000003240019000000000443004b00000000040000190000000104004039000001bd0530009c000002170000213d0000000104400190000002170000c13d000000400030043f0000000004020433000001d00540009c0000045f0000413d0000004401300039000001dc02000041000000000021043500000024013000390000000802000039000002b50000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000800220008c000000400000413d0000000402100370000000000202043b000001b60320009c000000400000213d0000002403100370000000000603043b000001b60360009c000000400000213d0000006403100370000000000503043b000001b60350009c000000400000213d000000000300041a0000fffe043001900000021d0000c13d000001e00330019700000102033001bf000000000030041b0000004401100370000000000401043b000000000102004b000002290000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f501000041000000610000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000200220008c000000400000413d0000000401100370000000000101043b000001b60210009c000000400000213d00000000001004350000000301000039000000200010043f00000040020000390000000001000019068106610000040f000000000101041a000001b601100197000000800010043f000001b801000041000006820001042e000f00000002001d000e00000004001d000001b9010000410000000000100439001000000003001d0000000400300443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000001004000029000000400000613d000000400500043d00000024015000390000000f020000290000000000210435000001bb0100004100000000001504350000000001000411000d00000001001d000001b601100197000000040250003900000000001204350000000001000414000000040240008c000002150000613d000001a202000041000001a20310009c0000000001028019000001a20350009c00000000020540190000004002200210000000c001100210000000000121019f000001bc011001c70000000002040019000c00000005001d068106770000040f0000000c05000029000000100400002900000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000002640000613d000001bd0150009c000002400000a13d000001f00100004100000000001004350000004101000039000000040010043f000001ef010000410000068300010430000001a601000041000000800010043f0000002001000039000000840010043f0000002e01000039000000a40010043f000001dd01000041000000c40010043f000001de01000041000000e40010043f000001df010000410000068300010430000000000104004b000002330000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f401000041000000610000013d001000000006001d000f00000004001d000e00000005001d000000000105004b000002870000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f301000041000000610000013d000000400050043f00000000004004350000000301000039000000200010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001be011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000400200043d0000002403200039000000000101043b000000000101041a000001b601100198000002c90000c13d000001a6010000410000000000120435000000040120003900000020040000390000000000410435000000020100003900000000001304350000004401200039000001c3030000410000000000310435000001a201000041000001a20320009c00000000020180190000004001200210000001c4011001c70000068300010430000000400200043d0000001f0430018f0000000505300272000002710000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000002690000413d000000000604004b000002800000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001a201000041000001a20420009c000000000201801900000040012002100000006002300210000000000121019f0000068300010430000001e1013001970000001002200210000001e202200197000000000121019f000000000010041b000001e3010000410000000000100439000000000100041200000004001004430000002400000443000001a2030000410000000001000414000001a20210009c0000000001038019000000c001100210000001e4011001c700008005020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000d00000001001d000001e50100004100000000001004390000000001000414000001a20210009c000001a201008041000000c001100210000001e6011001c70000800b020000390681067c0000040f00000001022001900000059c0000613d000000400200043d000c00000002001d000000000101043b0000000d0110006c0000034d0000c13d000000100100006b0000038f0000c13d0000000c030000290000004401300039000001f2020000410000000000210435000000240130003900000003020000390000000000210435000001a6010000410000000000130435000000040130003900000020020000390000000000210435000001a201000041000001a20230009c00000000030180190000004001300210000001c4011001c70000068300010430000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001c901000041000000610000013d0000002004200039000001bf0500004100000000005404350000000e04000029000000600440021000000000004304350000006001100210000000380320003900000000001304350000004c012000390000000f0300002900000000003104350000004c010000390000000000120435000001c00120009c000002170000213d0000008003200039000000400030043f000001c101000041000c00000003001d0000000000130435000000840120003900000020030000390000000000310435000000a40320003900000000010204330000000000130435000000c403200039000000000401004b000002ef0000613d000000000400001900000000053400190000002004400039000000000624001900000000060604330000000000650435000000000514004b000002e80000413d000000000231001900000000000204350000001f01100039000000200200008a000000000121016f000001a2020000410000000c04000029000001a20340009c0000000003020019000000000304401900000040033002100000004401100039000001a20410009c00000000010280190000006001100210000000000131019f0000000003000414000001a20430009c0000000003028019000000c002300210000000000112019f0000800802000039068106770000040f0000000c0a00002900000000030100190000006003300270000001a203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000003190000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000003110000413d000000000705004b000003280000613d0000000506600210000000000761034f0000000c066000290000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000003720000613d0000001f01400039000000600210018f0000000c01200029000000000221004b00000000020000190000000102004039000001bd0410009c00000010070000290000000e05000029000002170000213d0000000102200190000002170000c13d000000400010043f000000200230008c000000400000413d0000000f020000290000000000210435000001a2020000410000000003000414000001a20430009c0000000003028019000001a20410009c00000000010280190000004001100210000000c002300210000000000112019f000001a8011001c7000001b6065001970000800d020000390000000403000039000001c2040000410000000d05000029000003a80000013d0000000c01000029000001e70110009c000002170000813d0000000c040000290000002401400039000001e8020000410000000000210435000000440140003900000000020004140000006003000039001000000003001d0000000000310435000001e90100004100000000001404350000006401400039000000000001043500000004014000390000000000010435000001a201000041000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000121019f000001ea011001c70000800602000039068106770000040f0000000102200190000003fc0000613d000000000201043b000000000102004b000004380000c13d00000003010003670000000102000031000004010000013d000000400200043d0000001f0430018f00000005053002720000037f0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000003770000413d000000000604004b0000038e0000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d0000000401000039000000000201041a000001d90220019700000010022001af000000000021041b000001f101000041000000000200041a000000000112016f000000000010041b00000002010000390000000c040000290000000000140435000001a2010000410000000002000414000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000112019f000001a8011001c70000800d020000390000000103000039000001a904000041068106770000040f0000000101200190000000400000613d0000000001000019000006820001042e0000000f0110006c000004260000c13d000001b901000041000000000010043900000006010000290000000400100443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000e02000029000000400000613d000000400400043d00000024014000390000000d030000290000000000310435000001da010000410000000000140435000001b602200197001000000004001d0000000401400039000f00000002001d000000000021043500000000010004140000000602000029000000040220008c000003e30000613d000001a202000041000001a20310009c00000000010280190000001004000029000001a20340009c00000000020440190000004002200210000000c001100210000000000121019f000001bc011001c70000000602000029068106770000040f00000000030100190000006003300270000101a20030019d000001a203300197000300000001035500000001022001900000059d0000613d0000001001000029000001bd0110009c000002170000213d0000001004000029000000400040043f0000000d010000290000000000140435000001a2010000410000000002000414000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000112019f000001a8011001c70000000c02000029000001b6052001970000800d020000390000000403000039000001db040000410000000f060000290000000607000029000003a80000013d000300000001035500000000020100190000006002200270000101a20020019d000001a202200197000000400300043d0000001f0420018f00000005052002720000040e0000613d000000000600001900000005076002100000000008730019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000004060000413d000000000604004b0000041d0000613d0000000505500210000000000151034f00000000055300190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001a201000041000001a20430009c0000000003018019000001a20420009c000000000201801900000060012002100000004002300210000000000112019f0000068300010430000000400100043d0000004402100039000001ce030000410000000000320435000000240210003900000007030000290000000000320435000001a6020000410000000000210435000000040210003900000020030000390000000000320435000001a202000041000001a20310009c00000000010280190000004001100210000001c4011001c70000068300010430000000400100043d000001eb0310009c000002170000213d000001b602200197000000840310003900000000002304350000002402100039000001ec0300004100000000003204350000006402100039000000000300041400000020040000390000000000420435000000440210003900000010040000290000000000420435000001e902000041000000000021043500000004021000390000000000020435000001a202000041000001a20430009c0000000003028019000001a20410009c00000000010280190000004001100210000000c002300210000000000121019f000001ed011001c70000800602000039068106770000040f00000001022001900000053c0000613d000000000101043b000000000201004b0000055e0000c13d00000003010003670000000102000031000005410000013d000000c001100210000001d1011001970000004002200210000001d202200041000001d302200197000000000121019f0000006002400210000001d402200197000000000121019f000001d5011001c700008006020000390000000003000019000000000400001900000000050000190000000006000019068106770000040f000300000001035500000000030100190000006003300270000101a20030019d000001a2053001970000003f03500039000001a306300197000000400400043d0000000003460019000000000663004b00000000060000190000000106004039000001bd0730009c000002170000213d0000000106600190000002170000c13d000000400030043f00000000035404360000001f0650003900000005066002720000048f0000613d0000000007000031000000020770036700000000080000190000000509800210000000000a930019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000004870000413d000000000600004b000004910000613d0000001f0650018f00000005055002720000049d0000613d000000000700001900000005087002100000000009830019000000000881034f000000000808043b00000000008904350000000107700039000000000857004b000004950000413d000000000706004b000004ac0000613d0000000505500210000000000151034f00000000055300190000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f00000000001504350000000101200190000005ba0000613d0000000001040433000001c702000041000000200410008c00000000040000190000000004024019000001c701100197000000000501004b000000000200a019000001c70110009c000000000204c019000000000102004b000000400000c13d0000000001030433000800000001001d000001b60110009c000000400000213d000001b901000041000000000010043900000008010000290000000400100443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000f020000290000000b04000029000000400000613d000000400300043d000001d701000041000000000013043500000024053000390000000901000029000300000005001d00000000001504350000000401300039000200000001001d00000000002104350000001f0240018f0000006401300039000900000003001d0000004403300039000100000003001d0000000000430435000000100300002900000002033003670000000504400272000004ee0000613d000000000500001900000005065002100000000007610019000000000663034f000000000606043b00000000006704350000000105500039000000000645004b000004e60000413d000000000502004b000004fd0000613d0000000504400210000000000343034f00000000044100190000000302200210000000000504043300000000052501cf000000000525022f000000000303043b0000010002200089000000000323022f00000000022301cf000000000252019f00000000002404350000000b01100029000000000001043500000000010004140000000802000029000000040220008c0000051e0000613d0000000b020000290000001f022000390000000a0220017f000001a2030000410000000905000029000001a20450009c0000000004030019000000000405401900000040044002100000006402200039000001a20520009c00000000020380190000006002200210000000000224019f000001a20410009c0000000001038019000000c001100210000000000121019f0000000802000029068106770000040f00000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000005db0000613d0000000901000029000001bd0110009c000002170000213d0000000901000029000000400010043f0000000802000029000000050120014f000001b601100198000005f80000c13d000000060100002900000000001004350000000401000029000000200010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001be011001c700008010020000390681067c0000040f00000001022001900000000f03000029000000400000613d000000000101043b000000000201041a000001d902200197000000000232019f000000000021041b000003af0000013d000300000001035500000000020100190000006002200270000101a20020019d000001a202200197000000400300043d0000001f0420018f00000005052002720000054e0000613d000000000600001900000005076002100000000008730019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005460000413d000000000604004b0000055d0000613d0000000505500210000000000151034f00000000055300190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000041d0000013d000001b6031001970000000101000039000000000201041a000001d902200197000000000232019f000000000021041b00000002010000390000000f02000029000000000021041b000001b9010000410000000000100439001000000003001d0000000400300443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000e02000029000000400000613d000000400300043d000001ee010000410000000000130435000c00000003001d0000000401300039000000000021043500000000010004140000001002000029000000040220008c000005960000613d000001a202000041000001a20310009c00000000010280190000000c04000029000001a20340009c00000000020440190000004002200210000000c001100210000000000121019f000001ef011001c70000001002000029068106770000040f00000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000005be0000613d0000000c01000029000001bd0110009c000002170000213d0000000c01000029000000400010043f000003940000013d000000000001042f000000400200043d0000001f0430018f0000000505300272000005aa0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005a20000413d000000000604004b000005b90000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000000400100043d0000004402100039000001d603000041000004290000013d000000400200043d0000001f0430018f0000000505300272000005cb0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005c30000413d000000000604004b000002800000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000000400200043d0000001f0430018f0000000505300272000005e80000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005e00000413d000000000604004b000005f70000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000001a60100004100000009030000290000000000130435000000200100003900000002020000290000000000120435000000070100002900000003020000290000000000120435000001d80100004100000001020000290000000000120435000002bb0000013d0001000000000002000100000001001d0000000101000039000000000301041a000000400100043d00000040021000390000004004000039000000000042043500000060020000390000000002210436000001b603300197000000000032043500000060031000390000000000030435000001f60310009c000006580000813d0000008003100039000000400030043f000001a203000041000001a20420009c000000000203801900000040022002100000000001010433000001a20410009c00000000010380190000006001100210000000000121019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f00000001022001900000065e0000613d0000000202000039000000000202041a000000000301043b000000400100043d000000a0041000390000000000340435000000800310003900000000002304350000000102000029000001b602200197000000600310003900000000002304350000004002100039000000000300041000000000003204350000002002100039000001cb030000410000000000320435000000a0030000390000000000310435000001cc0310009c000006580000213d000000c003100039000000400030043f000001a203000041000001a20420009c000000000203801900000040022002100000000001010433000001a20410009c00000000010380190000006001100210000000000121019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f00000001022001900000065e0000613d000000000101043b000001b601100197000000000001042d000001f00100004100000000001004350000004101000039000000040010043f000001ef01000041000006830001043000000000010000190000068300010430000000000001042f000001a203000041000001a20410009c00000000010380190000004001100210000001a20420009c00000000020380190000006002200210000000000112019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f0000000102200190000006750000613d000000000101043b000000000001042d000000000100001900000683000104300000067a002104210000000102000039000000000001042d0000000002000019000000000001042d0000067f002104230000000102000039000000000001042d0000000002000019000000000001042d0000068100000432000006820001042e0000068300010430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe0616c697a696e6700000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320696e69746908c379a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008400000000000000000000000002000000000000000000000000000000000000200000000000000000000000007f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498000000020000000000000000000000000000008000000100000000000000000000000000000000000000000000000000000000000000000000000000cfe7af7b00000000000000000000000000000000000000000000000000000000f54266a100000000000000000000000000000000000000000000000000000000f54266a200000000000000000000000000000000000000000000000000000000f5f1516800000000000000000000000000000000000000000000000000000000cfe7af7c00000000000000000000000000000000000000000000000000000000d9caed1200000000000000000000000000000000000000000000000000000000a31ee5af00000000000000000000000000000000000000000000000000000000a31ee5b000000000000000000000000000000000000000000000000000000000b852ad36000000000000000000000000000000000000000000000000000000006dde720900000000000000000000000000000000000000000000000000000000969b53da000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000008000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83020000020000000000000000000000000000002400000000000000000000000074f4f547000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff020000000000000000000000000000000000004000000000000000000000000011a2ccc100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f62f84b24000000000000000000000000000000000000000000000000000000002fc3848834aac8e883a2d2a17a7514dc4f2d3dd268089df9b9f5d918259ef3b079680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000416d6f756e742063616e6e6f74206265207a65726f000000000000000000000000000000000000000000000000000000000000640000008000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eeeeffffffffffffffffffffffffffffffffeeef6d710000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000060000000a000000000000000002020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494000000000000000000000000000000000000000000000000ffffffffffffff3f020000000000000000000000000000000000000000000000000000000000000067670000000000000000000000000000000000000000000000000000000000003cda335100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000ffffffff000000000000000000000000000000000000000000000000ffffffff00000000000000000000000001000000000000000000000000000000000000000000000000000000000000006d6b00000000000000000000000000000000000000000000000000000000000095f11a40000000000000000000000000000000000000000000000000000000006d74000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000008c2a993e00000000000000000000000000000000000000000000000000000000b84fba9af218da60d299dc177abd5805e7ac541d2673cbee7808c10017874f634f766572666c6f77000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65640000000000000000000000000000000000000000000000000000000000000000000000000084000000800000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffffff0000000000000000000000000000000000000000010200000000000000000000ffffffffffffffffffffffffffffffffffffffff0000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e02000002000000000000000000000000000000440000000000000000000000009a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b0200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7c010004751688ab9322961547058fd0f36d3edf69880b64cbb2857041d33f4a133cda33511d41a8a5431b1770c5bc0ddd62e1cd30555d16659b89c0d60f4f9f570200000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7b010000691fa4f751f8312bc555242f18ed78cdc9aabc0ea77d7d5a675ee8ac6f02000000000000000000000000000000000000a4000000000000000000000000f2fde38b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6266320000000000000000000000000000000000000000000000000000000000736600000000000000000000000000000000000000000000000000000000000064660000000000000000000000000000000000000000000000000000000000006266000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff800000000000000000000000000000000000000000000000000000000000000000f5cf0be6820df44d868e986d4d5cafabd5702ac45d181a5ac4eb5ed59a001b03", - "deployedBytecode": "0x0004000000000002001000000000000200000000030100190000006004300270000001a20340019700030000003103550002000000010355000001a20040019d00000001022001900000001d0000c13d0000008002000039000000400020043f000000040230008c000000400000413d000000000201043b000000e002200270000001ab0420009c000000420000213d000001b10420009c0000008a0000213d000001b40120009c000000c10000613d000001b50120009c000000400000c13d0000000001000416000000000101004b000000400000c13d0000000401000039000001d90000013d0000000002000416000000000202004b000000400000c13d000000bf02300039000001a302200197000000400020043f0000001f0230018f00000005043002720000002f0000613d00000000050000190000000506500210000000000761034f000000000707043b000000a00660003900000000007604350000000105500039000000000645004b000000270000413d000000000502004b0000003e0000613d0000000504400210000000000141034f0000000302200210000000a004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f0000000000140435000000200130008c000000640000813d00000000010000190000068300010430000001ac0420009c000000940000213d000001af0420009c000000c60000613d000001b00220009c000000400000c13d0000000002000416000000000202004b000000400000c13d000000040230008a000000600220008c000000400000413d0000000402100370000000000402043b000001b60240009c000000400000213d0000002402100370000000000302043b000001b60230009c000000400000213d0000004401100370000000000201043b000000000102004b000001de0000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000001501000039000000a40010043f000001c501000041000000c40010043f000001c6010000410000068300010430000000a00100043d000000800010043f000000000200041a0000ff0003200190000000ac0000c13d000000ff0320018f000000ff0330008c000000820000613d000000ff012001bf000000000010041b000000ff01000039000000400200043d0000000000120435000001a2010000410000000003000414000001a20430009c0000000003018019000001a20420009c00000000020180190000004001200210000000c002300210000000000112019f000001a8011001c70000800d020000390000000103000039000001a904000041068106770000040f0000000101200190000000400000613d000000800100043d000001400000044300000160001004430000002001000039000001000010044300000001010000390000012000100443000001aa01000041000006820001042e000001b20420009c000001a50000613d000001b30120009c000000400000c13d0000000001000416000000000101004b000000400000c13d000000000100041a0000001001100270000001da0000013d000001ad0420009c000001c90000613d000001ae0220009c000000400000c13d0000000002000416000000000202004b000000400000c13d000000040230008a000000200220008c000000400000413d0000000401100370000000000101043b000001b60210009c000000400000213d068106050000040f000001b601100197000000400200043d0000000000120435000001a201000041000001a20320009c00000000020180190000004001200210000001b7011001c7000006820001042e000000400100043d0000006402100039000001a40300004100000000003204350000004402100039000001a5030000410000000000320435000000240210003900000027030000390000000000320435000001a6020000410000000000210435000000040210003900000020030000390000000000320435000001a202000041000001a20310009c00000000010280190000004001100210000001a7011001c700000683000104300000000001000416000000000101004b000000400000c13d0000000101000039000001d90000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000a00220008c000000400000413d0000000402100370000000000802043b000001b60280009c000000400000213d0000002402100370000000000902043b000001b60290009c000000400000213d0000004402100370000000000a02043b000001b602a0009c000000400000213d0000008402100370000000000202043b000001bd0420009c000000400000213d0000002304200039000001c705000041000000000634004b00000000060000190000000006058019000001c704400197000000000704004b0000000005008019000001c70440009c000000000506c019000000000405004b000000400000c13d0000000404200039000000000441034f000000000504043b000001bd0450009c000000400000213d001000240020003d0000001002500029000000000232004b000000400000213d000b00000005001d000f0000000a001d000e00000009001d000c00000008001d0000006401100370000000000101043b000d00000001001d0000000001000411000001c801100041000001b6011001970000000402000039000000000202041a000001b602200197000000000221004b000001050000613d000000000200041a0000001002200270000001b602200197000000000121004b000002c10000c13d0000000101000039000800000001001d000000000101041a000001b601100197000000a00010043f0000004001000039000900000001001d000000c00010043f000000e00000043f0000006001000039000a00000001001d000000800010043f0000010001000039000000400010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ca011001c700008010020000390681067c0000040f00000001022001900000000f05000029000000400000613d0000000202000039000700000002001d000000000202041a000000000301043b000000400100043d000000a004100039000000000034043500000080031000390000000000230435000000600210003900000000005204350000004002100039000000000300041000000000003204350000002002100039000001cb030000410000000000320435000000a0030000390000000000310435000001cc0310009c000002170000213d000000c003100039000000400030043f000001a204000041000001a20320009c000000000204801900000040022002100000000001010433000001a20310009c00000000010480190000006001100210000000000121019f0000000002000414000001a20320009c0000000002048019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000000101043b000500000001001d000001b601100197000600000001001d00000000001004350000000301000039000400000001001d000000200010043f0000000001000414000001a20210009c000001a201008041000000c001100210000001be011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000000101043b000000000101041a000001b601100198000003ad0000c13d00000000010004140000000702000029000000000402041a0000000802000029000000000202041a000000400300043d000000400530003900000009060000290000000000650435000001b602200197000000200530003900000000002504350000000a02000029000000000023043500000060023000390000000000020435000001c00230009c000002170000213d0000008002300039000000400020043f000000a005300039000001cf060000410000000000650435000000e4053000390000000a060000290000000000650435000000c4053000390000000000450435000000a4043000390000000f0500002900000000005404350000010405300039000000000403043300000000004504350000012405300039000000000604004b0000018a0000613d000000000600001900000000075600190000002006600039000000000836001900000000080804330000000000870435000000000746004b000001830000413d000000000354001900000000000304350000001f03400039000a0020000000920000000a0330017f00000084043000390000000000420435000000c3033000390000000a0430017f0000000003240019000000000443004b00000000040000190000000104004039000001bd0530009c000002170000213d0000000104400190000002170000c13d000000400030043f0000000004020433000001d00540009c0000045f0000413d0000004401300039000001dc02000041000000000021043500000024013000390000000802000039000002b50000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000800220008c000000400000413d0000000402100370000000000202043b000001b60320009c000000400000213d0000002403100370000000000603043b000001b60360009c000000400000213d0000006403100370000000000503043b000001b60350009c000000400000213d000000000300041a0000fffe043001900000021d0000c13d000001e00330019700000102033001bf000000000030041b0000004401100370000000000401043b000000000102004b000002290000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f501000041000000610000013d0000000002000416000000000202004b000000400000c13d000000040230008a000000200220008c000000400000413d0000000401100370000000000101043b000001b60210009c000000400000213d00000000001004350000000301000039000000200010043f00000040020000390000000001000019068106610000040f000000000101041a000001b601100197000000800010043f000001b801000041000006820001042e000f00000002001d000e00000004001d000001b9010000410000000000100439001000000003001d0000000400300443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000001004000029000000400000613d000000400500043d00000024015000390000000f020000290000000000210435000001bb0100004100000000001504350000000001000411000d00000001001d000001b601100197000000040250003900000000001204350000000001000414000000040240008c000002150000613d000001a202000041000001a20310009c0000000001028019000001a20350009c00000000020540190000004002200210000000c001100210000000000121019f000001bc011001c70000000002040019000c00000005001d068106770000040f0000000c05000029000000100400002900000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000002640000613d000001bd0150009c000002400000a13d000001f00100004100000000001004350000004101000039000000040010043f000001ef010000410000068300010430000001a601000041000000800010043f0000002001000039000000840010043f0000002e01000039000000a40010043f000001dd01000041000000c40010043f000001de01000041000000e40010043f000001df010000410000068300010430000000000104004b000002330000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f401000041000000610000013d001000000006001d000f00000004001d000e00000005001d000000000105004b000002870000c13d000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001f301000041000000610000013d000000400050043f00000000004004350000000301000039000000200010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001be011001c700008010020000390681067c0000040f0000000102200190000000400000613d000000400200043d0000002403200039000000000101043b000000000101041a000001b601100198000002c90000c13d000001a6010000410000000000120435000000040120003900000020040000390000000000410435000000020100003900000000001304350000004401200039000001c3030000410000000000310435000001a201000041000001a20320009c00000000020180190000004001200210000001c4011001c70000068300010430000000400200043d0000001f0430018f0000000505300272000002710000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000002690000413d000000000604004b000002800000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001a201000041000001a20420009c000000000201801900000040012002100000006002300210000000000121019f0000068300010430000001e1013001970000001002200210000001e202200197000000000121019f000000000010041b000001e3010000410000000000100439000000000100041200000004001004430000002400000443000001a2030000410000000001000414000001a20210009c0000000001038019000000c001100210000001e4011001c700008005020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000d00000001001d000001e50100004100000000001004390000000001000414000001a20210009c000001a201008041000000c001100210000001e6011001c70000800b020000390681067c0000040f00000001022001900000059c0000613d000000400200043d000c00000002001d000000000101043b0000000d0110006c0000034d0000c13d000000100100006b0000038f0000c13d0000000c030000290000004401300039000001f2020000410000000000210435000000240130003900000003020000390000000000210435000001a6010000410000000000130435000000040130003900000020020000390000000000210435000001a201000041000001a20230009c00000000030180190000004001300210000001c4011001c70000068300010430000001a601000041000000800010043f0000002001000039000000840010043f0000000201000039000000a40010043f000001c901000041000000610000013d0000002004200039000001bf0500004100000000005404350000000e04000029000000600440021000000000004304350000006001100210000000380320003900000000001304350000004c012000390000000f0300002900000000003104350000004c010000390000000000120435000001c00120009c000002170000213d0000008003200039000000400030043f000001c101000041000c00000003001d0000000000130435000000840120003900000020030000390000000000310435000000a40320003900000000010204330000000000130435000000c403200039000000000401004b000002ef0000613d000000000400001900000000053400190000002004400039000000000624001900000000060604330000000000650435000000000514004b000002e80000413d000000000231001900000000000204350000001f01100039000000200200008a000000000121016f000001a2020000410000000c04000029000001a20340009c0000000003020019000000000304401900000040033002100000004401100039000001a20410009c00000000010280190000006001100210000000000131019f0000000003000414000001a20430009c0000000003028019000000c002300210000000000112019f0000800802000039068106770000040f0000000c0a00002900000000030100190000006003300270000001a203300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000003190000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b000003110000413d000000000705004b000003280000613d0000000506600210000000000761034f0000000c066000290000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000100000003001f00030000000103550000000102200190000003720000613d0000001f01400039000000600210018f0000000c01200029000000000221004b00000000020000190000000102004039000001bd0410009c00000010070000290000000e05000029000002170000213d0000000102200190000002170000c13d000000400010043f000000200230008c000000400000413d0000000f020000290000000000210435000001a2020000410000000003000414000001a20430009c0000000003028019000001a20410009c00000000010280190000004001100210000000c002300210000000000112019f000001a8011001c7000001b6065001970000800d020000390000000403000039000001c2040000410000000d05000029000003a80000013d0000000c01000029000001e70110009c000002170000813d0000000c040000290000002401400039000001e8020000410000000000210435000000440140003900000000020004140000006003000039001000000003001d0000000000310435000001e90100004100000000001404350000006401400039000000000001043500000004014000390000000000010435000001a201000041000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000121019f000001ea011001c70000800602000039068106770000040f0000000102200190000003fc0000613d000000000201043b000000000102004b000004380000c13d00000003010003670000000102000031000004010000013d000000400200043d0000001f0430018f00000005053002720000037f0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000003770000413d000000000604004b0000038e0000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d0000000401000039000000000201041a000001d90220019700000010022001af000000000021041b000001f101000041000000000200041a000000000112016f000000000010041b00000002010000390000000c040000290000000000140435000001a2010000410000000002000414000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000112019f000001a8011001c70000800d020000390000000103000039000001a904000041068106770000040f0000000101200190000000400000613d0000000001000019000006820001042e0000000f0110006c000004260000c13d000001b901000041000000000010043900000006010000290000000400100443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000e02000029000000400000613d000000400400043d00000024014000390000000d030000290000000000310435000001da010000410000000000140435000001b602200197001000000004001d0000000401400039000f00000002001d000000000021043500000000010004140000000602000029000000040220008c000003e30000613d000001a202000041000001a20310009c00000000010280190000001004000029000001a20340009c00000000020440190000004002200210000000c001100210000000000121019f000001bc011001c70000000602000029068106770000040f00000000030100190000006003300270000101a20030019d000001a203300197000300000001035500000001022001900000059d0000613d0000001001000029000001bd0110009c000002170000213d0000001004000029000000400040043f0000000d010000290000000000140435000001a2010000410000000002000414000001a20320009c0000000002018019000001a20340009c00000000040180190000004001400210000000c002200210000000000112019f000001a8011001c70000000c02000029000001b6052001970000800d020000390000000403000039000001db040000410000000f060000290000000607000029000003a80000013d000300000001035500000000020100190000006002200270000101a20020019d000001a202200197000000400300043d0000001f0420018f00000005052002720000040e0000613d000000000600001900000005076002100000000008730019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000004060000413d000000000604004b0000041d0000613d0000000505500210000000000151034f00000000055300190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000001a201000041000001a20430009c0000000003018019000001a20420009c000000000201801900000060012002100000004002300210000000000112019f0000068300010430000000400100043d0000004402100039000001ce030000410000000000320435000000240210003900000007030000290000000000320435000001a6020000410000000000210435000000040210003900000020030000390000000000320435000001a202000041000001a20310009c00000000010280190000004001100210000001c4011001c70000068300010430000000400100043d000001eb0310009c000002170000213d000001b602200197000000840310003900000000002304350000002402100039000001ec0300004100000000003204350000006402100039000000000300041400000020040000390000000000420435000000440210003900000010040000290000000000420435000001e902000041000000000021043500000004021000390000000000020435000001a202000041000001a20430009c0000000003028019000001a20410009c00000000010280190000004001100210000000c002300210000000000121019f000001ed011001c70000800602000039068106770000040f00000001022001900000053c0000613d000000000101043b000000000201004b0000055e0000c13d00000003010003670000000102000031000005410000013d000000c001100210000001d1011001970000004002200210000001d202200041000001d302200197000000000121019f0000006002400210000001d402200197000000000121019f000001d5011001c700008006020000390000000003000019000000000400001900000000050000190000000006000019068106770000040f000300000001035500000000030100190000006003300270000101a20030019d000001a2053001970000003f03500039000001a306300197000000400400043d0000000003460019000000000663004b00000000060000190000000106004039000001bd0730009c000002170000213d0000000106600190000002170000c13d000000400030043f00000000035404360000001f0650003900000005066002720000048f0000613d0000000007000031000000020770036700000000080000190000000509800210000000000a930019000000000997034f000000000909043b00000000009a04350000000108800039000000000968004b000004870000413d000000000600004b000004910000613d0000001f0650018f00000005055002720000049d0000613d000000000700001900000005087002100000000009830019000000000881034f000000000808043b00000000008904350000000107700039000000000857004b000004950000413d000000000706004b000004ac0000613d0000000505500210000000000151034f00000000055300190000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f00000000001504350000000101200190000005ba0000613d0000000001040433000001c702000041000000200410008c00000000040000190000000004024019000001c701100197000000000501004b000000000200a019000001c70110009c000000000204c019000000000102004b000000400000c13d0000000001030433000800000001001d000001b60110009c000000400000213d000001b901000041000000000010043900000008010000290000000400100443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000f020000290000000b04000029000000400000613d000000400300043d000001d701000041000000000013043500000024053000390000000901000029000300000005001d00000000001504350000000401300039000200000001001d00000000002104350000001f0240018f0000006401300039000900000003001d0000004403300039000100000003001d0000000000430435000000100300002900000002033003670000000504400272000004ee0000613d000000000500001900000005065002100000000007610019000000000663034f000000000606043b00000000006704350000000105500039000000000645004b000004e60000413d000000000502004b000004fd0000613d0000000504400210000000000343034f00000000044100190000000302200210000000000504043300000000052501cf000000000525022f000000000303043b0000010002200089000000000323022f00000000022301cf000000000252019f00000000002404350000000b01100029000000000001043500000000010004140000000802000029000000040220008c0000051e0000613d0000000b020000290000001f022000390000000a0220017f000001a2030000410000000905000029000001a20450009c0000000004030019000000000405401900000040044002100000006402200039000001a20520009c00000000020380190000006002200210000000000224019f000001a20410009c0000000001038019000000c001100210000000000121019f0000000802000029068106770000040f00000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000005db0000613d0000000901000029000001bd0110009c000002170000213d0000000901000029000000400010043f0000000802000029000000050120014f000001b601100198000005f80000c13d000000060100002900000000001004350000000401000029000000200010043f000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001be011001c700008010020000390681067c0000040f00000001022001900000000f03000029000000400000613d000000000101043b000000000201041a000001d902200197000000000232019f000000000021041b000003af0000013d000300000001035500000000020100190000006002200270000101a20020019d000001a202200197000000400300043d0000001f0420018f00000005052002720000054e0000613d000000000600001900000005076002100000000008730019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005460000413d000000000604004b0000055d0000613d0000000505500210000000000151034f00000000055300190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000041d0000013d000001b6031001970000000101000039000000000201041a000001d902200197000000000232019f000000000021041b00000002010000390000000f02000029000000000021041b000001b9010000410000000000100439001000000003001d0000000400300443000001a2010000410000000002000414000001a20320009c0000000002018019000000c001200210000001ba011001c700008002020000390681067c0000040f00000001022001900000059c0000613d000000000101043b000000000101004b0000000e02000029000000400000613d000000400300043d000001ee010000410000000000130435000c00000003001d0000000401300039000000000021043500000000010004140000001002000029000000040220008c000005960000613d000001a202000041000001a20310009c00000000010280190000000c04000029000001a20340009c00000000020440190000004002200210000000c001100210000000000121019f000001ef011001c70000001002000029068106770000040f00000000030100190000006003300270000101a20030019d000001a20330019700030000000103550000000102200190000005be0000613d0000000c01000029000001bd0110009c000002170000213d0000000c01000029000000400010043f000003940000013d000000000001042f000000400200043d0000001f0430018f0000000505300272000005aa0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005a20000413d000000000604004b000005b90000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000000400100043d0000004402100039000001d603000041000004290000013d000000400200043d0000001f0430018f0000000505300272000005cb0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005c30000413d000000000604004b000002800000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000000400200043d0000001f0430018f0000000505300272000005e80000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005e00000413d000000000604004b000005f70000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000002800000013d000001a60100004100000009030000290000000000130435000000200100003900000002020000290000000000120435000000070100002900000003020000290000000000120435000001d80100004100000001020000290000000000120435000002bb0000013d0001000000000002000100000001001d0000000101000039000000000301041a000000400100043d00000040021000390000004004000039000000000042043500000060020000390000000002210436000001b603300197000000000032043500000060031000390000000000030435000001f60310009c000006580000813d0000008003100039000000400030043f000001a203000041000001a20420009c000000000203801900000040022002100000000001010433000001a20410009c00000000010380190000006001100210000000000121019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f00000001022001900000065e0000613d0000000202000039000000000202041a000000000301043b000000400100043d000000a0041000390000000000340435000000800310003900000000002304350000000102000029000001b602200197000000600310003900000000002304350000004002100039000000000300041000000000003204350000002002100039000001cb030000410000000000320435000000a0030000390000000000310435000001cc0310009c000006580000213d000000c003100039000000400030043f000001a203000041000001a20420009c000000000203801900000040022002100000000001010433000001a20410009c00000000010380190000006001100210000000000121019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f00000001022001900000065e0000613d000000000101043b000001b601100197000000000001042d000001f00100004100000000001004350000004101000039000000040010043f000001ef01000041000006830001043000000000010000190000068300010430000000000001042f000001a203000041000001a20410009c00000000010380190000004001100210000001a20420009c00000000020380190000006002200210000000000112019f0000000002000414000001a20420009c0000000002038019000000c002200210000000000112019f000001cd011001c700008010020000390681067c0000040f0000000102200190000006750000613d000000000101043b000000000001042d000000000100001900000683000104300000067a002104210000000102000039000000000001042d0000000002000019000000000001042d0000067f002104230000000102000039000000000001042d0000000002000019000000000001042d0000068100000432000006820001042e0000068300010430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe0616c697a696e6700000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320696e69746908c379a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008400000000000000000000000002000000000000000000000000000000000000200000000000000000000000007f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498000000020000000000000000000000000000008000000100000000000000000000000000000000000000000000000000000000000000000000000000cfe7af7b00000000000000000000000000000000000000000000000000000000f54266a100000000000000000000000000000000000000000000000000000000f54266a200000000000000000000000000000000000000000000000000000000f5f1516800000000000000000000000000000000000000000000000000000000cfe7af7c00000000000000000000000000000000000000000000000000000000d9caed1200000000000000000000000000000000000000000000000000000000a31ee5af00000000000000000000000000000000000000000000000000000000a31ee5b000000000000000000000000000000000000000000000000000000000b852ad36000000000000000000000000000000000000000000000000000000006dde720900000000000000000000000000000000000000000000000000000000969b53da000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000008000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83020000020000000000000000000000000000002400000000000000000000000074f4f547000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff020000000000000000000000000000000000004000000000000000000000000011a2ccc100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f62f84b24000000000000000000000000000000000000000000000000000000002fc3848834aac8e883a2d2a17a7514dc4f2d3dd268089df9b9f5d918259ef3b079680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000416d6f756e742063616e6e6f74206265207a65726f000000000000000000000000000000000000000000000000000000000000640000008000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eeeeffffffffffffffffffffffffffffffffeeef6d710000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000060000000a000000000000000002020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494000000000000000000000000000000000000000000000000ffffffffffffff3f020000000000000000000000000000000000000000000000000000000000000067670000000000000000000000000000000000000000000000000000000000003cda335100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000ffffffff000000000000000000000000000000000000000000000000ffffffff00000000000000000000000001000000000000000000000000000000000000000000000000000000000000006d6b00000000000000000000000000000000000000000000000000000000000095f11a40000000000000000000000000000000000000000000000000000000006d74000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000008c2a993e00000000000000000000000000000000000000000000000000000000b84fba9af218da60d299dc177abd5805e7ac541d2673cbee7808c10017874f634f766572666c6f77000000000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65640000000000000000000000000000000000000000000000000000000000000000000000000084000000800000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffffff0000000000000000000000000000000000000000010200000000000000000000ffffffffffffffffffffffffffffffffffffffff0000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e02000002000000000000000000000000000000440000000000000000000000009a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b0200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7c010004751688ab9322961547058fd0f36d3edf69880b64cbb2857041d33f4a133cda33511d41a8a5431b1770c5bc0ddd62e1cd30555d16659b89c0d60f4f9f570200000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7b010000691fa4f751f8312bc555242f18ed78cdc9aabc0ea77d7d5a675ee8ac6f02000000000000000000000000000000000000a4000000000000000000000000f2fde38b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff6266320000000000000000000000000000000000000000000000000000000000736600000000000000000000000000000000000000000000000000000000000064660000000000000000000000000000000000000000000000000000000000006266000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff800000000000000000000000000000000000000000000000000000000000000000f5cf0be6820df44d868e986d4d5cafabd5702ac45d181a5ac4eb5ed59a001b03", - "linkReferences": {}, - "deployedLinkReferences": {}, - "factoryDeps": { - "0x010000691fa4f751f8312bc555242f18ed78cdc9aabc0ea77d7d5a675ee8ac6f": "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol:UpgradeableBeacon", - "0x010004751688ab9322961547058fd0f36d3edf69880b64cbb2857041d33f4a13": "contracts/bridge/L2StandardERC20.sol:L2StandardERC20" - } -} diff --git a/l1-contracts/script-config/artifacts/TransparentUpgradeableProxy.json b/l1-contracts/script-config/artifacts/TransparentUpgradeableProxy.json deleted file mode 100644 index c8880c120..000000000 --- a/l1-contracts/script-config/artifacts/TransparentUpgradeableProxy.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "_format": "hh-zksolc-artifact-1", - "contractName": "TransparentUpgradeableProxy", - "sourceName": "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "_logic", - "type": "address" - }, - { - "internalType": "address", - "name": "admin_", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } - ], - "bytecode": "0x00020000000000020008000000000002000000000301001900000060033002700000012c0330019700010000003103550000008008000039000000400080043f00000001022001900000001e0000c13d000000000431034f00000000050004110000013d02000041000000000702041a0000013002700197000000000603004b000000270000c13d000000000325004b0000010c0000c13d000000000101043b0000014101100197000001420310009c0000001b0000613d000001430310009c000002c20000613d000001440310009c000002680000c13d00000000010004160000000001000019000004ac000104300000012d023000410000012e0220009c0000005f0000213d000001520100004100000000001004350000004101000039000000040010043f0000015301000041000004ac00010430000000000525004b0000012d0000c13d000000000401043b0000014104400197000001420540009c000001670000c13d0000000002000416000000000202004b000002c20000c13d000000240230008c000002c20000413d0000000401100370000000000201043b000001300120009c000002c20000213d000000a001000039000000400010043f000000800000043f00000133010000410000000000100439000800000002001d00000004002004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000002a80000c13d000000400100043d00000064021000390000015403000041000000000032043500000044021000390000015503000041000000000032043500000024021000390000002d0300003900000000003204350000013c0200004100000000002104350000000402100039000000200300003900000000003204350000012c020000410000012c0310009c000000000102801900000040011002100000014c011001c7000004ac000104300000009f023000390000012f02200197000000400020043f0000001f0230018f00000005043002720000006e0000613d00000000050000190000000506500210000000000761034f000000000707043b000000800660003900000000007604350000000105500039000000000645004b000000660000413d000000000502004b0000007d0000613d0000000504400210000000000141034f00000003022002100000008004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f00000000001404350000005f0130008c000002c20000a13d000000800900043d000001300190009c000002c20000213d000000a00700043d000001300170009c000002c20000213d000000c00200043d000001310120009c000002c20000213d0000001f012000390000013204000041000000000531004b000000000500001900000000050480190000013201100197000000000601004b0000000004008019000001320110009c000000000405c019000000000104004b000002c20000c13d00000080012000390000000001010433000001310410009c000000210000213d0000003f04100039000000200a00008a0000000004a4016f000000400b00043d00000000044b00190000000005b4004b00000000050000190000000105004039000001310640009c000000210000213d0000000105500190000000210000c13d0000008003300039000000400040043f00000000061b0436000000a0022000390000000004210019000000000334004b000002c20000213d00060000000b001d00050000000a001d000700000007001d000300000008001d000000000301004b000000b90000613d000000000300001900000000046300190000000005230019000000000505043300000000005404350000002003300039000000000413004b000000b20000413d000400000006001d0000000001160019000000000001043500000133010000410000000000100439000800000009001d00000004009004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000004a0000613d000000080100002900000130051001970000013501000041000000000201041a0000013602200197000000000252019f000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f0000000803000029000000010120019000000007020000290000000605000029000002c20000613d0000000001050433000000000101004b000003770000c13d0000013d01000041000000000301041a0000013004200197000000400100043d0000002002100039000800000004001d0000000000420435000700000003001d000001300230019700000000002104350000012c0200004100000000030004140000012c0430009c00000000030280190000012c0410009c00000000010280190000004001100210000000c002300210000000000112019f0000013e011001c70000800d0200003900000001030000390000013f0400004104aa049b0000040f0000000101200190000002c20000613d000000080100006b0000025a0000613d0000000701000029000001360110019700000008011001af0000013d02000041000000000012041b0000002001000039000001000010044300000120000004430000014001000041000004ab0001042e0000013501000041000000000201041a00000000010004140000013002200197000000040320008c000001e90000c13d00000000030000310000001f0230018f00000005013002720000011e0000613d00000000050000190000000506500210000000000764034f000000000707043b00000000007604350000000105500039000000000615004b000001170000413d000000000502004b0000020e0000613d00000003022002100000000501100210000000000501043300000000052501cf000000000525022f000000000414034f000000000404043b0000010002200089000000000424022f00000000022401cf000000000252019f00000000002104350000020e0000013d0000001f0530018f0000013502000041000000000202041a000001300220019700000005063002720000013b0000613d00000000070000190000000508700210000000000981034f000000000909043b00000000009804350000000107700039000000000867004b000001340000413d000000000705004b000001490000613d00000003055002100000000506600210000000000706043300000000075701cf000000000757022f000000000161034f000000000101043b0000010005500089000000000151022f00000000015101cf000000000171019f00000000001604350000000001000414000000040520008c0000020f0000c13d00000000030000310000001f0230018f0000000501300272000001580000613d00000000050000190000000506500210000000000764034f000000000707043b00000000007604350000000105500039000000000615004b000001510000413d000000000502004b000002360000613d00000003022002100000000501100210000000000501043300000000052501cf000000000525022f000000000414034f000000000404043b0000010002200089000000000424022f00000000022401cf000000000252019f0000000000210435000002360000013d000001430540009c0000023b0000c13d000000440230008c000002c20000413d0000000402100370000000000802043b000001300280009c000002c20000213d0000002402100370000000000402043b000001310240009c000002c20000213d00000023024000390000013205000041000000000632004b000000000600001900000000060580190000013202200197000000000702004b0000000005008019000001320220009c000000000506c019000000000205004b000002c20000c13d0000000405400039000000000251034f000000000202043b000001310620009c000000210000213d000000bf06200039000000200900008a000000000696016f000001310760009c000000210000213d000000400060043f000000800020043f00000000042400190000002404400039000000000334004b000002c20000213d0000002003500039000000000131034f0000001f0320018f00000005042002720000019d0000613d00000000050000190000000506500210000000000761034f000000000707043b000000a00660003900000000007604350000000105500039000000000645004b000001950000413d000700000009001d000000000503004b000001ad0000613d0000000504400210000000000141034f0000000303300210000000a004400039000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f0000000000140435000000a001200039000000000001043500000133010000410000000000100439000800000008001d00000004008004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000004a0000613d0000013501000041000000000201041a000001360220019700000008022001af0000000805000029000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f00000008030000290000000101200190000002c20000613d000000400100043d000600000001001d000001390110009c000000210000213d00000006040000290000006001400039000000400010043f00000040014000390000013a02000041000000000021043500000020014000390000013b02000041000000000021043500000027010000390000000000140435000000800200043d0000000001000414000000040330008c0000040d0000c13d000000010200003900000000040000310000041d0000013d0000012c030000410000012c0410009c0000000001038019000000c00110021004aa04a50000040f0001000000010355000000000301001900000060033002700000001f0430018f0000012c0030019d0000012c033001970000000505300272000001fe0000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000001f70000413d000000000604004b0000020c0000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000000101200190000002640000613d000002360000013d0000012c040000410000012c0510009c0000000001048019000000c0011002100000006003300210000000000131019f04aa04a50000040f0001000000010355000000000301001900000060033002700000001f0430018f0000012c0030019d0000012c033001970000000505300272000002260000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b0000021f0000413d000000000604004b000002340000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000000101200190000002660000613d0000012c010000410000012c0230009c00000000030180190000006001300210000004ab0001042e000001440540009c0000026e0000c13d0000000004000416000000000404004b000002c20000c13d000000240330008c000002c20000413d0000000401100370000000000401043b000001300140009c000002c20000213d000000800020043f000000a00040043f0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000148011001c70000800d020000390000000103000039000700000004001d0000013f04000041000800000007001d04aa049b0000040f000000070400002900000008030000290000000101200190000002c20000613d000000000104004b000002c40000c13d000000400100043d00000064021000390000014a03000041000000000032043500000044021000390000014b03000041000000000032043500000024021000390000002603000039000000530000013d0000006001300210000004ac000104300000006001300210000004ac00010430000001450310009c000002750000c13d0000000001000416000000000101004b000002c20000c13d0000027d0000013d000001450140009c000002840000c13d0000000001000416000000000101004b000002c20000c13d000000a00020043f0000028d0000013d000001460110009c0000029a0000c13d0000000001000416000000000101004b000002c20000c13d0000013501000041000000000101041a0000013002100197000000a00020043f0000002001000039000000800010043f000000c001000039000000400010043f0000015a01000041000004ab0001042e000001460140009c0000029a0000c13d0000000001000416000000000101004b000002c20000c13d0000013501000041000000000101041a0000013001100197000000a00010043f0000002001000039000000800010043f000000c001000039000000400010043f000000800100003900000147020000410000015003000041000001500410009c000000000103801900000040011002100000015101100041000000000121019f000004ab0001042e0000013c01000041000000800010043f0000002001000039000000840010043f0000004201000039000000a40010043f0000015601000041000000c40010043f0000015701000041000000e40010043f0000015801000041000001040010043f0000015901000041000004ac000104300000013501000041000000000201041a000001360220019700000008022001af0000000805000029000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f00000008080000290000000101200190000002c20000613d000000800100043d000000000101004b000002d00000c13d000000400100043d000001490210009c000000210000213d000002cb0000013d0000000001000019000004ac000104300000013601300197000000000114019f0000013d02000041000000000012041b000000400100043d000001490210009c000000210000213d0000002002100039000000400020043f00000000000104350000000002000019000002930000013d000000400900043d000001390190009c000000210000213d0000006001900039000000400010043f00000040019000390000013a02000041000000000021043500000020019000390000013b02000041000000000021043500000027010000390000000000190435000000800200043d0000000001000414000000040380008c000002e40000c13d00000001020000390000000004000031000002f70000013d0000012c030000410000012c0410009c00000000010380190000012c0420009c00000000020380190000006002200210000000c001100210000000000121019f0000014d011001c70000000002080019000700000009001d04aa04a50000040f00000007090000290000000808000029000000010220018f000100000001035500000060011002700000012c0010019d0000012c0410019700000060030000390000008001000039000000000504004b000003230000c13d0000000003030433000000000202004b000003530000c13d000000000203004b0000038c0000c13d000000400100043d0000013c0200004100000000002104350000000402100039000000200300003900000000003204350000000002090433000000240310003900000000002304350000004403100039000000000402004b000003140000613d000000000400001900000000053400190000002004400039000000000694001900000000060604330000000000650435000000000524004b0000030d0000413d0000001f04200039000000200500008a000000000454016f0000000002320019000000000002043500000044024000390000012c030000410000012c0420009c00000000020380190000012c0410009c000000000103801900000040011002100000006002200210000000000112019f000004ac00010430000001310140009c000000210000213d0000003f01400039000000200300008a000000000131016f000000400300043d0000000001130019000000000531004b00000000050000190000000105004039000001310610009c000000210000213d0000000105500190000000210000c13d000000000a090019000000400010043f0000001f0540018f000000000143043600000001060003670000000504400272000003410000613d000000000700001900000005087002100000000009810019000000000886034f000000000808043b00000000008904350000000107700039000000000847004b000003390000413d000000000705004b000000080800002900000000090a0019000002fb0000613d0000000504400210000000000646034f00000000044100190000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000002fb0000013d000000000103004b000002be0000c13d0000013301000041000000000010043900000004008004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000002be0000c13d000000400100043d00000044021000390000014e03000041000000000032043500000024021000390000001d0300003900000000003204350000013c0200004100000000002104350000000402100039000000200300003900000000003204350000012c020000410000012c0310009c000000000102801900000040011002100000014f011001c7000004ac00010430000000400400043d000001390140009c000000210000213d0000006001400039000000400010043f00000040014000390000013a0200004100000000002104350000002701000039000200000004001d00000000021404360000013b01000041000100000002001d000000000012043500000000020504330000000001000414000000040330008c000003950000c13d00000001020000390000000003000031000003a90000013d0000012c020000410000012c0430009c00000000030280190000012c0410009c000000000102801900000040011002100000006002300210000000000112019f000004ac000104300000012c0300004100000004050000290000012c0450009c000000000503801900000040045002100000012c0520009c00000000020380190000006002200210000000000242019f0000012c0410009c0000000001038019000000c001100210000000000112019f000000080200002904aa04a50000040f000000010220018f000100000001035500000060011002700000012c0010019d0000012c031001970000006001000039000000000403004b000003c90000c13d0000000001010433000000000202004b000003f70000c13d000000000201004b000004830000c13d000000400400043d000800000004001d0000013c01000041000000000014043500000004014000390000002002000039000000000021043500000002010000290000000003010433000700000003001d000000240140003900000000003104350000004402400039000000010100002904aa048d0000040f00000007010000290000001f01100039000000050110017f00000044011000390000012c020000410000012c0310009c00000000010280190000000804000029000004870000013d000001310130009c0000000504000029000000210000213d0000003f01300039000000000441016f000000400100043d0000000004410019000000000514004b00000000050000190000000105004039000001310640009c000000210000213d0000000105500190000000210000c13d000000400040043f0000001f0430018f000000000931043600000001050003670000000503300272000003e60000613d000000000600001900000005076002100000000008790019000000000775034f000000000707043b00000000007804350000000106600039000000000736004b000003de0000413d000300000009001d000000000604004b000003ac0000613d0000000503300210000000000535034f00000003033000290000000304400210000000000603043300000000064601cf000000000646022f000000000505043b0000010004400089000000000545022f00000000044501cf000000000464019f0000000000430435000003ac0000013d000000000101004b00000007020000290000000803000029000000e60000c13d0000013301000041000000000010043900000004003004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000000702000029000000e60000c13d000003650000013d0000012c030000410000012c0410009c00000000010380190000012c0420009c00000000020380190000006002200210000000c001100210000000000121019f0000014d011001c7000000080200002904aa04a50000040f000000010220018f000100000001035500000060011002700000012c0010019d0000012c0410019700000060030000390000008001000039000000000504004b0000043e0000c13d0000000003030433000000000202004b0000046b0000c13d000000000203004b0000038c0000c13d000000400100043d0000013c02000041000000000021043500000004021000390000002003000039000000000032043500000006070000290000000002070433000000240310003900000000002304350000004403100039000000000402004b0000043b0000613d000000000400001900000000053400190000002004400039000000000674001900000000060604330000000000650435000000000524004b000004340000413d0000001f042000390000000705000029000003160000013d000001310140009c0000000703000029000000210000213d0000003f01400039000000000131016f000000400300043d0000000001130019000000000531004b00000000050000190000000105004039000001310610009c000000210000213d0000000105500190000000210000c13d000000400010043f0000001f0540018f0000000001430436000000010600036700000005044002720000045b0000613d000000000700001900000005087002100000000009810019000000000886034f000000000808043b00000000008904350000000107700039000000000847004b000004530000413d000000000705004b000004210000613d0000000504400210000000000646034f00000000044100190000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000004210000013d000000000103004b0000047e0000c13d00000133010000410000000000100439000000080100002900000004001004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000003650000613d000000400100043d000001490210009c000000210000213d000002cb0000013d000000000001042f0000012c020000410000012c0310009c000000000102801900000003040000290000012c0340009c000000000402801900000040024002100000006001100210000000000121019f000004ac00010430000000000403004b000004970000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000534004b000004900000413d00000000012300190000000000010435000000000001042d000000000001042f0000049e002104210000000102000039000000000001042d0000000002000019000000000001042d000004a3002104230000000102000039000000000001042d0000000002000019000000000001042d000004a8002104250000000102000039000000000001042d0000000002000019000000000001042d000004aa00000432000004ab0001042e000004ac0001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009fffffffffffffffffffffffffffffffffffffffffffffffff000000000000007f00000000000000000000000000000000000000000000000000000001ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff80000000000000000000000000000000000000000000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcffffffffffffffffffffffff00000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000bc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b000000000000000000000000000000000000000000000000ffffffffffffff9f206661696c656400000000000000000000000000000000000000000000000000416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c08c379a000000000000000000000000000000000000000000000000000000000b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610302000000000000000000000000000000000000400000000000000000000000007e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f0000000200000000000000000000000000000040000001000000000000000000ffffffff000000000000000000000000000000000000000000000000000000003659cfe6000000000000000000000000000000000000000000000000000000004f1ef286000000000000000000000000000000000000000000000000000000008f28397000000000000000000000000000000000000000000000000000000000f851a440000000000000000000000000000000000000000000000000000000005c60da1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000200000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf6464726573730000000000000000000000000000000000000000000000000000455243313936373a206e65772061646d696e20697320746865207a65726f206100000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffdf00000000000000000000000000000000000000000000002000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000006f74206120636f6e747261637400000000000000000000000000000000000000455243313936373a206e657720696d706c656d656e746174696f6e206973206e5472616e73706172656e745570677261646561626c6550726f78793a2061646d696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a40000008000000000000000000000000000000000000000000000000000000020000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000007444ff0b02dc9864c7dbf97ccd7719c286d6972190eeb0285ea9e04a713977c0", - "deployedBytecode": "0x00020000000000020008000000000002000000000301001900000060033002700000012c0330019700010000003103550000008008000039000000400080043f00000001022001900000001e0000c13d000000000431034f00000000050004110000013d02000041000000000702041a0000013002700197000000000603004b000000270000c13d000000000325004b0000010c0000c13d000000000101043b0000014101100197000001420310009c0000001b0000613d000001430310009c000002c20000613d000001440310009c000002680000c13d00000000010004160000000001000019000004ac000104300000012d023000410000012e0220009c0000005f0000213d000001520100004100000000001004350000004101000039000000040010043f0000015301000041000004ac00010430000000000525004b0000012d0000c13d000000000401043b0000014104400197000001420540009c000001670000c13d0000000002000416000000000202004b000002c20000c13d000000240230008c000002c20000413d0000000401100370000000000201043b000001300120009c000002c20000213d000000a001000039000000400010043f000000800000043f00000133010000410000000000100439000800000002001d00000004002004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000002a80000c13d000000400100043d00000064021000390000015403000041000000000032043500000044021000390000015503000041000000000032043500000024021000390000002d0300003900000000003204350000013c0200004100000000002104350000000402100039000000200300003900000000003204350000012c020000410000012c0310009c000000000102801900000040011002100000014c011001c7000004ac000104300000009f023000390000012f02200197000000400020043f0000001f0230018f00000005043002720000006e0000613d00000000050000190000000506500210000000000761034f000000000707043b000000800660003900000000007604350000000105500039000000000645004b000000660000413d000000000502004b0000007d0000613d0000000504400210000000000141034f00000003022002100000008004400039000000000504043300000000052501cf000000000525022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000151019f00000000001404350000005f0130008c000002c20000a13d000000800900043d000001300190009c000002c20000213d000000a00700043d000001300170009c000002c20000213d000000c00200043d000001310120009c000002c20000213d0000001f012000390000013204000041000000000531004b000000000500001900000000050480190000013201100197000000000601004b0000000004008019000001320110009c000000000405c019000000000104004b000002c20000c13d00000080012000390000000001010433000001310410009c000000210000213d0000003f04100039000000200a00008a0000000004a4016f000000400b00043d00000000044b00190000000005b4004b00000000050000190000000105004039000001310640009c000000210000213d0000000105500190000000210000c13d0000008003300039000000400040043f00000000061b0436000000a0022000390000000004210019000000000334004b000002c20000213d00060000000b001d00050000000a001d000700000007001d000300000008001d000000000301004b000000b90000613d000000000300001900000000046300190000000005230019000000000505043300000000005404350000002003300039000000000413004b000000b20000413d000400000006001d0000000001160019000000000001043500000133010000410000000000100439000800000009001d00000004009004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000004a0000613d000000080100002900000130051001970000013501000041000000000201041a0000013602200197000000000252019f000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f0000000803000029000000010120019000000007020000290000000605000029000002c20000613d0000000001050433000000000101004b000003770000c13d0000013d01000041000000000301041a0000013004200197000000400100043d0000002002100039000800000004001d0000000000420435000700000003001d000001300230019700000000002104350000012c0200004100000000030004140000012c0430009c00000000030280190000012c0410009c00000000010280190000004001100210000000c002300210000000000112019f0000013e011001c70000800d0200003900000001030000390000013f0400004104aa049b0000040f0000000101200190000002c20000613d000000080100006b0000025a0000613d0000000701000029000001360110019700000008011001af0000013d02000041000000000012041b0000002001000039000001000010044300000120000004430000014001000041000004ab0001042e0000013501000041000000000201041a00000000010004140000013002200197000000040320008c000001e90000c13d00000000030000310000001f0230018f00000005013002720000011e0000613d00000000050000190000000506500210000000000764034f000000000707043b00000000007604350000000105500039000000000615004b000001170000413d000000000502004b0000020e0000613d00000003022002100000000501100210000000000501043300000000052501cf000000000525022f000000000414034f000000000404043b0000010002200089000000000424022f00000000022401cf000000000252019f00000000002104350000020e0000013d0000001f0530018f0000013502000041000000000202041a000001300220019700000005063002720000013b0000613d00000000070000190000000508700210000000000981034f000000000909043b00000000009804350000000107700039000000000867004b000001340000413d000000000705004b000001490000613d00000003055002100000000506600210000000000706043300000000075701cf000000000757022f000000000161034f000000000101043b0000010005500089000000000151022f00000000015101cf000000000171019f00000000001604350000000001000414000000040520008c0000020f0000c13d00000000030000310000001f0230018f0000000501300272000001580000613d00000000050000190000000506500210000000000764034f000000000707043b00000000007604350000000105500039000000000615004b000001510000413d000000000502004b000002360000613d00000003022002100000000501100210000000000501043300000000052501cf000000000525022f000000000414034f000000000404043b0000010002200089000000000424022f00000000022401cf000000000252019f0000000000210435000002360000013d000001430540009c0000023b0000c13d000000440230008c000002c20000413d0000000402100370000000000802043b000001300280009c000002c20000213d0000002402100370000000000402043b000001310240009c000002c20000213d00000023024000390000013205000041000000000632004b000000000600001900000000060580190000013202200197000000000702004b0000000005008019000001320220009c000000000506c019000000000205004b000002c20000c13d0000000405400039000000000251034f000000000202043b000001310620009c000000210000213d000000bf06200039000000200900008a000000000696016f000001310760009c000000210000213d000000400060043f000000800020043f00000000042400190000002404400039000000000334004b000002c20000213d0000002003500039000000000131034f0000001f0320018f00000005042002720000019d0000613d00000000050000190000000506500210000000000761034f000000000707043b000000a00660003900000000007604350000000105500039000000000645004b000001950000413d000700000009001d000000000503004b000001ad0000613d0000000504400210000000000141034f0000000303300210000000a004400039000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f0000000000140435000000a001200039000000000001043500000133010000410000000000100439000800000008001d00000004008004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000004a0000613d0000013501000041000000000201041a000001360220019700000008022001af0000000805000029000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f00000008030000290000000101200190000002c20000613d000000400100043d000600000001001d000001390110009c000000210000213d00000006040000290000006001400039000000400010043f00000040014000390000013a02000041000000000021043500000020014000390000013b02000041000000000021043500000027010000390000000000140435000000800200043d0000000001000414000000040330008c0000040d0000c13d000000010200003900000000040000310000041d0000013d0000012c030000410000012c0410009c0000000001038019000000c00110021004aa04a50000040f0001000000010355000000000301001900000060033002700000001f0430018f0000012c0030019d0000012c033001970000000505300272000001fe0000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b000001f70000413d000000000604004b0000020c0000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000000101200190000002640000613d000002360000013d0000012c040000410000012c0510009c0000000001048019000000c0011002100000006003300210000000000131019f04aa04a50000040f0001000000010355000000000301001900000060033002700000001f0430018f0000012c0030019d0000012c033001970000000505300272000002260000613d00000000060000190000000507600210000000000871034f000000000808043b00000000008704350000000106600039000000000756004b0000021f0000413d000000000604004b000002340000613d00000003044002100000000505500210000000000605043300000000064601cf000000000646022f000000000151034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000000101200190000002660000613d0000012c010000410000012c0230009c00000000030180190000006001300210000004ab0001042e000001440540009c0000026e0000c13d0000000004000416000000000404004b000002c20000c13d000000240330008c000002c20000413d0000000401100370000000000401043b000001300140009c000002c20000213d000000800020043f000000a00040043f0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000148011001c70000800d020000390000000103000039000700000004001d0000013f04000041000800000007001d04aa049b0000040f000000070400002900000008030000290000000101200190000002c20000613d000000000104004b000002c40000c13d000000400100043d00000064021000390000014a03000041000000000032043500000044021000390000014b03000041000000000032043500000024021000390000002603000039000000530000013d0000006001300210000004ac000104300000006001300210000004ac00010430000001450310009c000002750000c13d0000000001000416000000000101004b000002c20000c13d0000027d0000013d000001450140009c000002840000c13d0000000001000416000000000101004b000002c20000c13d000000a00020043f0000028d0000013d000001460110009c0000029a0000c13d0000000001000416000000000101004b000002c20000c13d0000013501000041000000000101041a0000013002100197000000a00020043f0000002001000039000000800010043f000000c001000039000000400010043f0000015a01000041000004ab0001042e000001460140009c0000029a0000c13d0000000001000416000000000101004b000002c20000c13d0000013501000041000000000101041a0000013001100197000000a00010043f0000002001000039000000800010043f000000c001000039000000400010043f000000800100003900000147020000410000015003000041000001500410009c000000000103801900000040011002100000015101100041000000000121019f000004ab0001042e0000013c01000041000000800010043f0000002001000039000000840010043f0000004201000039000000a40010043f0000015601000041000000c40010043f0000015701000041000000e40010043f0000015801000041000001040010043f0000015901000041000004ac000104300000013501000041000000000201041a000001360220019700000008022001af0000000805000029000000000021041b0000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000137011001c70000800d020000390000000203000039000001380400004104aa049b0000040f00000008080000290000000101200190000002c20000613d000000800100043d000000000101004b000002d00000c13d000000400100043d000001490210009c000000210000213d000002cb0000013d0000000001000019000004ac000104300000013601300197000000000114019f0000013d02000041000000000012041b000000400100043d000001490210009c000000210000213d0000002002100039000000400020043f00000000000104350000000002000019000002930000013d000000400900043d000001390190009c000000210000213d0000006001900039000000400010043f00000040019000390000013a02000041000000000021043500000020019000390000013b02000041000000000021043500000027010000390000000000190435000000800200043d0000000001000414000000040380008c000002e40000c13d00000001020000390000000004000031000002f70000013d0000012c030000410000012c0410009c00000000010380190000012c0420009c00000000020380190000006002200210000000c001100210000000000121019f0000014d011001c70000000002080019000700000009001d04aa04a50000040f00000007090000290000000808000029000000010220018f000100000001035500000060011002700000012c0010019d0000012c0410019700000060030000390000008001000039000000000504004b000003230000c13d0000000003030433000000000202004b000003530000c13d000000000203004b0000038c0000c13d000000400100043d0000013c0200004100000000002104350000000402100039000000200300003900000000003204350000000002090433000000240310003900000000002304350000004403100039000000000402004b000003140000613d000000000400001900000000053400190000002004400039000000000694001900000000060604330000000000650435000000000524004b0000030d0000413d0000001f04200039000000200500008a000000000454016f0000000002320019000000000002043500000044024000390000012c030000410000012c0420009c00000000020380190000012c0410009c000000000103801900000040011002100000006002200210000000000112019f000004ac00010430000001310140009c000000210000213d0000003f01400039000000200300008a000000000131016f000000400300043d0000000001130019000000000531004b00000000050000190000000105004039000001310610009c000000210000213d0000000105500190000000210000c13d000000000a090019000000400010043f0000001f0540018f000000000143043600000001060003670000000504400272000003410000613d000000000700001900000005087002100000000009810019000000000886034f000000000808043b00000000008904350000000107700039000000000847004b000003390000413d000000000705004b000000080800002900000000090a0019000002fb0000613d0000000504400210000000000646034f00000000044100190000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000002fb0000013d000000000103004b000002be0000c13d0000013301000041000000000010043900000004008004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000002be0000c13d000000400100043d00000044021000390000014e03000041000000000032043500000024021000390000001d0300003900000000003204350000013c0200004100000000002104350000000402100039000000200300003900000000003204350000012c020000410000012c0310009c000000000102801900000040011002100000014f011001c7000004ac00010430000000400400043d000001390140009c000000210000213d0000006001400039000000400010043f00000040014000390000013a0200004100000000002104350000002701000039000200000004001d00000000021404360000013b01000041000100000002001d000000000012043500000000020504330000000001000414000000040330008c000003950000c13d00000001020000390000000003000031000003a90000013d0000012c020000410000012c0430009c00000000030280190000012c0410009c000000000102801900000040011002100000006002300210000000000112019f000004ac000104300000012c0300004100000004050000290000012c0450009c000000000503801900000040045002100000012c0520009c00000000020380190000006002200210000000000242019f0000012c0410009c0000000001038019000000c001100210000000000112019f000000080200002904aa04a50000040f000000010220018f000100000001035500000060011002700000012c0010019d0000012c031001970000006001000039000000000403004b000003c90000c13d0000000001010433000000000202004b000003f70000c13d000000000201004b000004830000c13d000000400400043d000800000004001d0000013c01000041000000000014043500000004014000390000002002000039000000000021043500000002010000290000000003010433000700000003001d000000240140003900000000003104350000004402400039000000010100002904aa048d0000040f00000007010000290000001f01100039000000050110017f00000044011000390000012c020000410000012c0310009c00000000010280190000000804000029000004870000013d000001310130009c0000000504000029000000210000213d0000003f01300039000000000441016f000000400100043d0000000004410019000000000514004b00000000050000190000000105004039000001310640009c000000210000213d0000000105500190000000210000c13d000000400040043f0000001f0430018f000000000931043600000001050003670000000503300272000003e60000613d000000000600001900000005076002100000000008790019000000000775034f000000000707043b00000000007804350000000106600039000000000736004b000003de0000413d000300000009001d000000000604004b000003ac0000613d0000000503300210000000000535034f00000003033000290000000304400210000000000603043300000000064601cf000000000646022f000000000505043b0000010004400089000000000545022f00000000044501cf000000000464019f0000000000430435000003ac0000013d000000000101004b00000007020000290000000803000029000000e60000c13d0000013301000041000000000010043900000004003004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b0000000702000029000000e60000c13d000003650000013d0000012c030000410000012c0410009c00000000010380190000012c0420009c00000000020380190000006002200210000000c001100210000000000121019f0000014d011001c7000000080200002904aa04a50000040f000000010220018f000100000001035500000060011002700000012c0010019d0000012c0410019700000060030000390000008001000039000000000504004b0000043e0000c13d0000000003030433000000000202004b0000046b0000c13d000000000203004b0000038c0000c13d000000400100043d0000013c02000041000000000021043500000004021000390000002003000039000000000032043500000006070000290000000002070433000000240310003900000000002304350000004403100039000000000402004b0000043b0000613d000000000400001900000000053400190000002004400039000000000674001900000000060604330000000000650435000000000524004b000004340000413d0000001f042000390000000705000029000003160000013d000001310140009c0000000703000029000000210000213d0000003f01400039000000000131016f000000400300043d0000000001130019000000000531004b00000000050000190000000105004039000001310610009c000000210000213d0000000105500190000000210000c13d000000400010043f0000001f0540018f0000000001430436000000010600036700000005044002720000045b0000613d000000000700001900000005087002100000000009810019000000000886034f000000000808043b00000000008904350000000107700039000000000847004b000004530000413d000000000705004b000004210000613d0000000504400210000000000646034f00000000044100190000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000004210000013d000000000103004b0000047e0000c13d00000133010000410000000000100439000000080100002900000004001004430000012c0100004100000000020004140000012c0320009c0000000002018019000000c00120021000000134011001c7000080020200003904aa04a00000040f0000000102200190000004820000613d000000000101043b000000000101004b000003650000613d000000400100043d000001490210009c000000210000213d000002cb0000013d000000000001042f0000012c020000410000012c0310009c000000000102801900000003040000290000012c0340009c000000000402801900000040024002100000006001100210000000000121019f000004ac00010430000000000403004b000004970000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000534004b000004900000413d00000000012300190000000000010435000000000001042d000000000001042f0000049e002104210000000102000039000000000001042d0000000002000019000000000001042d000004a3002104230000000102000039000000000001042d0000000002000019000000000001042d000004a8002104250000000102000039000000000001042d0000000002000019000000000001042d000004aa00000432000004ab0001042e000004ac0001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000009fffffffffffffffffffffffffffffffffffffffffffffffff000000000000007f00000000000000000000000000000000000000000000000000000001ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff80000000000000000000000000000000000000000000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcffffffffffffffffffffffff00000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000bc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b000000000000000000000000000000000000000000000000ffffffffffffff9f206661696c656400000000000000000000000000000000000000000000000000416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c08c379a000000000000000000000000000000000000000000000000000000000b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610302000000000000000000000000000000000000400000000000000000000000007e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f0000000200000000000000000000000000000040000001000000000000000000ffffffff000000000000000000000000000000000000000000000000000000003659cfe6000000000000000000000000000000000000000000000000000000004f1ef286000000000000000000000000000000000000000000000000000000008f28397000000000000000000000000000000000000000000000000000000000f851a440000000000000000000000000000000000000000000000000000000005c60da1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000200000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf6464726573730000000000000000000000000000000000000000000000000000455243313936373a206e65772061646d696e20697320746865207a65726f206100000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffdf00000000000000000000000000000000000000000000002000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000006f74206120636f6e747261637400000000000000000000000000000000000000455243313936373a206e657720696d706c656d656e746174696f6e206973206e5472616e73706172656e745570677261646561626c6550726f78793a2061646d696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267657400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a40000008000000000000000000000000000000000000000000000000000000020000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000007444ff0b02dc9864c7dbf97ccd7719c286d6972190eeb0285ea9e04a713977c0", - "linkReferences": {}, - "deployedLinkReferences": {}, - "factoryDeps": {} -} diff --git a/l1-contracts/src.ts/deploy.ts b/l1-contracts/src.ts/deploy.ts index d7ba372e4..7b96f6358 100644 --- a/l1-contracts/src.ts/deploy.ts +++ b/l1-contracts/src.ts/deploy.ts @@ -219,21 +219,11 @@ export class Deployer { public async deployChainAdmin(create2Salt: string, ethTxOptions: ethers.providers.TransactionRequest) { ethTxOptions.gasLimit ??= 10_000_000; - // Firstly, we deploy the access control restriction for the chain admin - const accessControlRestriction = await this.deployViaCreate2( - "AccessControlRestriction", - [0, this.ownerAddress], - create2Salt, - ethTxOptions - ); - if (this.verbose) { - console.log(`CONTRACTS_ACCESS_CONTROL_RESTRICTION_ADDR=${accessControlRestriction}`); - } - // Then we deploy the ChainAdmin contract itself + // We deploy the ChainAdmin contract itself const contractAddress = await this.deployViaCreate2( "ChainAdmin", - [[accessControlRestriction]], + [this.ownerAddress, ethers.constants.AddressZero], create2Salt, ethTxOptions ); diff --git a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol index ec90f0d66..32fd846db 100644 --- a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol @@ -340,11 +340,7 @@ contract ExperimentalBridgeTest is Test { bridgeHub.addToken(randomAddress); } - function test_addToken_cannotBeCalledByRandomAddress( - address randomAddress, - address randomCaller, - uint256 randomValue - ) public useRandomToken(randomValue) { + function test_addToken_cannotBeCalledByRandomAddress(address randomAddress, address randomCaller) public { vm.assume(randomCaller != bridgeOwner); vm.assume(randomCaller != bridgeHub.admin()); diff --git a/l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol deleted file mode 100644 index e5b45975f..000000000 --- a/l1-contracts/test/foundry/unit/concrete/governance/Governance/AccessControlRestriction.t.sol +++ /dev/null @@ -1,186 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {Test} from "forge-std/Test.sol"; - -import "openzeppelin-contracts/contracts/utils/Strings.sol"; -import "forge-std/console.sol"; -import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; -import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; -import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; -import {IAccessControlRestriction} from "contracts/governance/IAccessControlRestriction.sol"; -import {Utils} from "test/foundry/unit/concrete/Utils/Utils.sol"; -import {NoCallsProvided, AccessToFallbackDenied, AccessToFunctionDenied} from "contracts/common/L1ContractErrors.sol"; -import {Call} from "contracts/governance/Common.sol"; - -contract AccessRestrictionTest is Test { - AccessControlRestriction internal restriction; - ChainAdmin internal chainAdmin; - address owner; - address randomCaller; - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - function getChainAdminSelectors() public pure returns (bytes4[] memory) { - bytes4[] memory selectors = new bytes4[](12); - selectors[0] = IChainAdmin.getRestrictions.selector; - selectors[1] = IChainAdmin.isRestrictionActive.selector; - selectors[2] = IChainAdmin.addRestriction.selector; - selectors[3] = IChainAdmin.removeRestriction.selector; - - return selectors; - } - - function setUp() public { - owner = makeAddr("random address"); - randomCaller = makeAddr("random caller"); - - restriction = new AccessControlRestriction(0, owner); - address[] memory restrictions = new address[](1); - restrictions[0] = address(restriction); - - chainAdmin = new ChainAdmin(restrictions); - } - - function test_adminAsAddressZero() public { - vm.expectRevert("AccessControl: 0 default admin"); - new AccessControlRestriction(0, address(0)); - } - - function test_setRequiredRoleForCallByNotDefaultAdmin(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); - string memory revertMsg = string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(randomCaller), 20), - " is missing role ", - Strings.toHexString(uint256(DEFAULT_ADMIN_ROLE), 32) - ) - ); - - vm.expectRevert(bytes(revertMsg)); - vm.prank(randomCaller); - restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); - } - - function test_setRequiredRoleForCallAccessToFunctionDenied(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); - - vm.startPrank(owner); - restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); - vm.stopPrank(); - - Call memory call = Call({ - target: address(chainAdmin), - value: 0, - data: abi.encodeCall(IChainAdmin.getRestrictions, ()) - }); - - vm.expectRevert( - abi.encodeWithSelector( - AccessToFunctionDenied.selector, - address(chainAdmin), - chainAdminSelectors[0], - randomCaller - ) - ); - restriction.validateCall(call, randomCaller); - } - - function test_setRequiredRoleForCall(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); - - vm.expectEmit(true, true, false, true); - emit IAccessControlRestriction.RoleSet(address(chainAdmin), chainAdminSelectors[0], role); - - vm.startPrank(owner); - restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); - restriction.grantRole(role, randomCaller); - vm.stopPrank(); - - Call memory call = Call({ - target: address(chainAdmin), - value: 0, - data: abi.encodeCall(IChainAdmin.getRestrictions, ()) - }); - restriction.validateCall(call, randomCaller); - } - - function test_setRequiredRoleForFallbackByNotDefaultAdmin(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - string memory revertMsg = string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(uint160(randomCaller), 20), - " is missing role ", - Strings.toHexString(uint256(DEFAULT_ADMIN_ROLE), 32) - ) - ); - - vm.expectRevert(bytes(revertMsg)); - vm.prank(randomCaller); - restriction.setRequiredRoleForFallback(address(chainAdmin), role); - } - - function test_setRequiredRoleForFallbackAccessToFallbackDenied(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - vm.startPrank(owner); - restriction.setRequiredRoleForFallback(address(chainAdmin), role); - vm.stopPrank(); - - Call memory call = Call({target: address(chainAdmin), value: 0, data: ""}); - - vm.expectRevert(abi.encodeWithSelector(AccessToFallbackDenied.selector, address(chainAdmin), randomCaller)); - restriction.validateCall(call, randomCaller); - } - - function test_setRequiredRoleForFallback(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - vm.expectEmit(true, false, false, true); - emit IAccessControlRestriction.FallbackRoleSet(address(chainAdmin), role); - - vm.startPrank(owner); - restriction.setRequiredRoleForFallback(address(chainAdmin), role); - restriction.grantRole(role, randomCaller); - vm.stopPrank(); - - Call memory call = Call({target: address(chainAdmin), value: 0, data: ""}); - restriction.validateCall(call, randomCaller); - } - - function test_validateCallFunction(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - bytes4[] memory chainAdminSelectors = getChainAdminSelectors(); - vm.startPrank(owner); - restriction.setRequiredRoleForCall(address(chainAdmin), chainAdminSelectors[0], role); - restriction.grantRole(role, randomCaller); - vm.stopPrank(); - - Call memory call = Call({ - target: address(chainAdmin), - value: 0, - data: abi.encodeCall(IChainAdmin.getRestrictions, ()) - }); - restriction.validateCall(call, randomCaller); - } - - function test_validateCallFallback(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - vm.startPrank(owner); - restriction.setRequiredRoleForFallback(address(chainAdmin), role); - restriction.grantRole(role, randomCaller); - vm.stopPrank(); - - Call memory call = Call({target: address(chainAdmin), value: 0, data: ""}); - restriction.validateCall(call, randomCaller); - } -} diff --git a/l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol index 01a3c7dfd..735d54328 100644 --- a/l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/governance/Governance/ChainAdmin.t.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.24; import {Test} from "forge-std/Test.sol"; import "openzeppelin-contracts/contracts/utils/Strings.sol"; -import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; import {GettersFacet} from "contracts/state-transition/chain-deps/facets/Getters.sol"; @@ -14,7 +13,6 @@ import {Utils} from "test/foundry/unit/concrete/Utils/Utils.sol"; contract ChainAdminTest is Test { ChainAdmin internal chainAdmin; - AccessControlRestriction internal restriction; GettersFacet internal gettersFacet; address internal owner; @@ -26,69 +24,11 @@ contract ChainAdminTest is Test { function setUp() public { owner = makeAddr("random address"); - restriction = new AccessControlRestriction(0, owner); - address[] memory restrictions = new address[](1); - restrictions[0] = address(restriction); - - chainAdmin = new ChainAdmin(restrictions); + chainAdmin = new ChainAdmin(owner, address(0)); gettersFacet = new GettersFacet(); } - function test_getRestrictions() public { - address[] memory restrictions = chainAdmin.getRestrictions(); - assertEq(restrictions[0], address(restriction)); - } - - function test_isRestrictionActive() public { - bool isActive = chainAdmin.isRestrictionActive(address(restriction)); - assertEq(isActive, true); - } - - function test_addRestriction() public { - address[] memory restrictions = chainAdmin.getRestrictions(); - - vm.expectEmit(true, false, false, true); - emit IChainAdmin.RestrictionAdded(owner); - - vm.prank(address(chainAdmin)); - chainAdmin.addRestriction(owner); - } - - function test_addRestrictionRevert() public { - vm.startPrank(address(chainAdmin)); - chainAdmin.addRestriction(owner); - - vm.expectRevert(abi.encodeWithSelector(RestrictionWasAlreadyPresent.selector, owner)); - chainAdmin.addRestriction(owner); - vm.stopPrank(); - } - - function test_removeRestriction() public { - address[] memory restrictions = chainAdmin.getRestrictions(); - - vm.startPrank(address(chainAdmin)); - chainAdmin.addRestriction(owner); - - vm.expectEmit(true, false, false, true); - emit IChainAdmin.RestrictionRemoved(owner); - - chainAdmin.removeRestriction(owner); - vm.stopPrank(); - } - - function test_removeRestrictionRevert() public { - address[] memory restrictions = chainAdmin.getRestrictions(); - - vm.startPrank(address(chainAdmin)); - chainAdmin.addRestriction(owner); - chainAdmin.removeRestriction(owner); - - vm.expectRevert(abi.encodeWithSelector(RestrictionWasNotPresent.selector, owner)); - chainAdmin.removeRestriction(owner); - vm.stopPrank(); - } - function test_setUpgradeTimestamp(uint256 semverMinorVersionMultiplier, uint256 timestamp) public { (major, minor, patch) = gettersFacet.getSemverProtocolVersion(); uint256 protocolVersion = packSemver(major, minor, patch + 1, semverMinorVersionMultiplier); @@ -96,67 +36,43 @@ contract ChainAdminTest is Test { vm.expectEmit(true, false, false, true); emit IChainAdmin.UpdateUpgradeTimestamp(protocolVersion, timestamp); - vm.prank(address(chainAdmin)); + vm.prank(address(owner)); chainAdmin.setUpgradeTimestamp(protocolVersion, timestamp); } function test_multicallRevertNoCalls() public { - Call[] memory calls = new Call[](0); + IChainAdmin.Call[] memory calls = new IChainAdmin.Call[](0); + vm.prank(owner); vm.expectRevert(NoCallsProvided.selector); chainAdmin.multicall(calls, false); } function test_multicallRevertFailedCall() public { - Call[] memory calls = new Call[](1); - calls[0] = Call({target: address(chainAdmin), value: 0, data: abi.encodeCall(gettersFacet.getAdmin, ())}); + IChainAdmin.Call[] memory calls = new IChainAdmin.Call[](1); + calls[0] = IChainAdmin.Call({ + target: address(chainAdmin), + value: 0, + data: abi.encodeCall(gettersFacet.getAdmin, ()) + }); vm.expectRevert(); vm.prank(owner); chainAdmin.multicall(calls, true); } - function test_validateCallAccessToFunctionDenied(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - Call[] memory calls = new Call[](2); - calls[0] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getAdmin, ())}); - calls[1] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getVerifier, ())}); - - vm.prank(owner); - restriction.setRequiredRoleForCall(address(gettersFacet), gettersFacet.getAdmin.selector, role); - - vm.expectRevert( - abi.encodeWithSelector( - AccessToFunctionDenied.selector, - address(gettersFacet), - gettersFacet.getAdmin.selector, - owner - ) - ); - vm.prank(owner); - chainAdmin.multicall(calls, true); - } - - function test_validateCallAccessToFallbackDenied(bytes32 role) public { - vm.assume(role != DEFAULT_ADMIN_ROLE); - - Call[] memory calls = new Call[](2); - calls[0] = Call({target: address(gettersFacet), value: 0, data: ""}); - calls[1] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getVerifier, ())}); - - vm.prank(owner); - restriction.setRequiredRoleForFallback(address(gettersFacet), role); - - vm.expectRevert(abi.encodeWithSelector(AccessToFallbackDenied.selector, address(gettersFacet), owner)); - vm.prank(owner); - chainAdmin.multicall(calls, true); - } - function test_multicall() public { - Call[] memory calls = new Call[](2); - calls[0] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getAdmin, ())}); - calls[1] = Call({target: address(gettersFacet), value: 0, data: abi.encodeCall(gettersFacet.getVerifier, ())}); + IChainAdmin.Call[] memory calls = new IChainAdmin.Call[](2); + calls[0] = IChainAdmin.Call({ + target: address(gettersFacet), + value: 0, + data: abi.encodeCall(gettersFacet.getAdmin, ()) + }); + calls[1] = IChainAdmin.Call({ + target: address(gettersFacet), + value: 0, + data: abi.encodeCall(gettersFacet.getVerifier, ()) + }); vm.prank(owner); chainAdmin.multicall(calls, true); diff --git a/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol b/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol deleted file mode 100644 index 33858b38f..000000000 --- a/l1-contracts/test/foundry/unit/concrete/governance/Governance/PermanentRestriction.t.sol +++ /dev/null @@ -1,211 +0,0 @@ -pragma solidity 0.8.24; - -import "openzeppelin-contracts/contracts/utils/Strings.sol"; -import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; -import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; -import {StateTransitionManager} from "contracts/state-transition/StateTransitionManager.sol"; -import {DiamondInit} from "contracts/state-transition/chain-deps/DiamondInit.sol"; -import {PermanentRestriction} from "contracts/governance/PermanentRestriction.sol"; -import {IPermanentRestriction} from "contracts/governance/IPermanentRestriction.sol"; -import {ZeroAddress, ChainZeroAddress, NotAnAdmin, UnallowedImplementation, RemovingPermanentRestriction, CallNotAllowed} from "contracts/common/L1ContractErrors.sol"; -import {Call} from "contracts/governance/Common.sol"; -import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol"; -import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; -import {VerifierParams, FeeParams, PubdataPricingMode} from "contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol"; -import {IAdmin} from "contracts/state-transition/chain-interfaces/IAdmin.sol"; -import {AccessControlRestriction} from "contracts/governance/AccessControlRestriction.sol"; -import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; -import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; -import {StateTransitionManagerTest} from "test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol"; - -contract PermanentRestrictionTest is StateTransitionManagerTest { - ChainAdmin internal chainAdmin; - AccessControlRestriction internal restriction; - PermanentRestriction internal permRestriction; - - address internal owner; - address internal hyperchain; - - function setUp() public { - deploy(); - - createNewChainBridgehub(getDiamondCutData(address(diamondInit))); - - vm.stopPrank(); - - owner = makeAddr("owner"); - hyperchain = chainContractAddress.getHyperchain(chainId); - permRestriction = new PermanentRestriction(owner, bridgehub); - restriction = new AccessControlRestriction(0, owner); - address[] memory restrictions = new address[](1); - restrictions[0] = address(restriction); - chainAdmin = new ChainAdmin(restrictions); - } - - function test_ownerAsAddressZero() public { - vm.expectRevert(ZeroAddress.selector); - permRestriction = new PermanentRestriction(address(0), bridgehub); - } - - function test_allowAdminImplementation(bytes32 implementationHash) public { - vm.expectEmit(true, false, false, true); - emit IPermanentRestriction.AdminImplementationAllowed(implementationHash, true); - - vm.prank(owner); - permRestriction.allowAdminImplementation(implementationHash, true); - } - - function test_setAllowedData(bytes memory data) public { - vm.expectEmit(false, false, false, true); - emit IPermanentRestriction.AllowedDataChanged(data, true); - - vm.prank(owner); - permRestriction.setAllowedData(data, true); - } - - function test_setSelectorIsValidated(bytes4 selector) public { - vm.expectEmit(true, false, false, true); - emit IPermanentRestriction.SelectorValidationChanged(selector, true); - - vm.prank(owner); - permRestriction.setSelectorIsValidated(selector, true); - } - - function test_tryCompareAdminOfAChainIsAddressZero() public { - vm.expectRevert(ChainZeroAddress.selector); - permRestriction.tryCompareAdminOfAChain(address(0), owner); - } - - function test_tryCompareAdminOfAChainNotAHyperchain() public { - vm.expectRevert(); - permRestriction.tryCompareAdminOfAChain(makeAddr("random"), owner); - } - - function test_tryCompareAdminOfAChainNotAnAdmin() public { - vm.expectRevert(abi.encodeWithSelector(NotAnAdmin.selector, IZkSyncHyperchain(hyperchain).getAdmin(), owner)); - permRestriction.tryCompareAdminOfAChain(hyperchain, owner); - } - - function test_tryCompareAdminOfAChain() public { - permRestriction.tryCompareAdminOfAChain(hyperchain, newChainAdmin); - } - - function test_validateCallTooShortData() public { - Call memory call = Call({target: hyperchain, value: 0, data: ""}); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCallSetPendingAdminUnallowedImplementation() public { - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.setPendingAdmin.selector, owner) - }); - - vm.expectRevert(abi.encodeWithSelector(UnallowedImplementation.selector, owner.codehash)); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCallSetPendingAdminRemovingPermanentRestriction() public { - vm.prank(owner); - permRestriction.allowAdminImplementation(address(chainAdmin).codehash, true); - - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.setPendingAdmin.selector, address(chainAdmin)) - }); - - vm.expectRevert(RemovingPermanentRestriction.selector); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCallSetPendingAdmin() public { - vm.prank(owner); - permRestriction.allowAdminImplementation(address(chainAdmin).codehash, true); - - vm.prank(address(chainAdmin)); - chainAdmin.addRestriction(address(permRestriction)); - - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.setPendingAdmin.selector, address(chainAdmin)) - }); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCallNotValidatedSelector() public { - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.acceptAdmin.selector) - }); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCallCallNotAllowed() public { - vm.prank(owner); - permRestriction.setSelectorIsValidated(IAdmin.acceptAdmin.selector, true); - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.acceptAdmin.selector) - }); - - vm.expectRevert(abi.encodeWithSelector(CallNotAllowed.selector, call.data)); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function test_validateCall() public { - vm.prank(owner); - permRestriction.setSelectorIsValidated(IAdmin.acceptAdmin.selector, true); - Call memory call = Call({ - target: hyperchain, - value: 0, - data: abi.encodeWithSelector(IAdmin.acceptAdmin.selector) - }); - - vm.prank(owner); - permRestriction.setAllowedData(call.data, true); - - vm.startPrank(newChainAdmin); - permRestriction.validateCall(call, owner); - vm.stopPrank(); - } - - function createNewChainBridgehub(Diamond.DiamondCutData memory _diamondCut) internal { - vm.stopPrank(); - vm.startPrank(address(0)); - bridgehub.addStateTransitionManager(address(chainContractAddress)); - bridgehub.addToken(baseToken); - bridgehub.setSharedBridge(sharedBridge); - - bridgehub.createNewChain({ - _chainId: chainId, - _stateTransitionManager: address(chainContractAddress), - _baseToken: baseToken, - _salt: 0, - _admin: newChainAdmin, - _initData: getCreateInputData(_diamondCut, false) - }); - } -} diff --git a/l1-contracts/test/test_config/constant/hardhat.json b/l1-contracts/test/test_config/constant/hardhat.json index 0e63431f0..d73350137 100644 --- a/l1-contracts/test/test_config/constant/hardhat.json +++ b/l1-contracts/test/test_config/constant/hardhat.json @@ -3,96 +3,96 @@ "name": "DAI", "symbol": "DAI", "decimals": 18, - "address": "0xD6E49dd4fb0CA1549566869725d1820aDEb92Ae9" + "address": "0x9F5d1DA449A6c22CCCCE139acD98adD82797fEec" }, { "name": "wBTC", "symbol": "wBTC", "decimals": 8, - "address": "0xcee1f75F30B6908286Cd003C4228A5D9a2851FA4" + "address": "0x275E5aa56a705c8726eE35B3DC6530DE0a0e5f6c" }, { "name": "BAT", "symbol": "BAT", "decimals": 18, - "address": "0x0Bc76A4EfE0748f1697F237fB100741ea6Ceda2d" + "address": "0x18d8b7878Ee8D1cf3c32b177e0B0EC2379084B11" }, { "name": "GNT", "symbol": "GNT", "decimals": 18, - "address": "0x51ae50BcCEE10ac5BEFFA1E4a64106a5f83bc3F8" + "address": "0xe4B41b2c8e3831cbEdC8b3D82047fA30B6B22946" }, { "name": "MLTT", "symbol": "MLTT", "decimals": 18, - "address": "0xa9c7fEEf8586E17D93A05f873BA65f28f48ED259" + "address": "0xe8c976ce9F855825e52015bd1E88Fc84Da1946d2" }, { "name": "DAIK", "symbol": "DAIK", "decimals": 18, - "address": "0x99Efb27598804Aa408A1066550e9d01c45f21b05" + "address": "0xd012f213dDD34858A1357e30B4c491dbFCba8Ee3" }, { "name": "wBTCK", "symbol": "wBTCK", "decimals": 8, - "address": "0x4B701928Da6B3e72775b462A15b8b76ba2d16BbD" + "address": "0x8fbdf8cEAf04E3cc9ac53C90b344c0c2489a0645" }, { "name": "BATK", "symbol": "BATS", "decimals": 18, - "address": "0xf7B03c921dfefB4286b13075BA0335099708368D" + "address": "0x91D6cBBb7006A3fC6686d65375A067624b8D405A" }, { "name": "GNTK", "symbol": "GNTS", "decimals": 18, - "address": "0xc0581Ee28c519533B06cc0aAC1ace98cF63C817b" + "address": "0xEbD3994f1a9d85458bD2a40Fc6927C4048291067" }, { "name": "MLTTK", "symbol": "MLTTS", "decimals": 18, - "address": "0xeB6394F2E8DA607b94dBa2Cf345A965d6D9b3aCD" + "address": "0x194475D0de71858B134e2084fa627B5A7d04334c" }, { "name": "DAIL", "symbol": "DAIL", "decimals": 18, - "address": "0x4311643C5eD7cD0813B4E3Ff5428de71c7d7b8bB" + "address": "0xfB6306147E50e7042E74eA6Cc3db38a8489F8D78" }, { "name": "wBTCL", "symbol": "wBTCP", "decimals": 8, - "address": "0x6b3fbfC9Bb89Ab5F11BE782a1f67c1615c2A5fc3" + "address": "0xA50C21DE8a2d575F915E5f8D6D5ec8eF2935D58e" }, { "name": "BATL", "symbol": "BATW", "decimals": 18, - "address": "0xE003698b7831829843B69D3fB4f9a3133d97b257" + "address": "0xCBaDEF24FA67dB5a56fD84c72b22797A125C3132" }, { "name": "GNTL", "symbol": "GNTW", "decimals": 18, - "address": "0x2417626170675Ccf6022d9db1eFC8f3c59836368" + "address": "0x80C92D6E8d4015660506Cf4F4503eBF3bc073190" }, { "name": "MLTTL", "symbol": "MLTTW", "decimals": 18, - "address": "0x28106C39BE5E51C31D9a289313361D86C9bb7C8E" + "address": "0x44bD975d5735ab2E1b61787228f538e13bF263DC" }, { "name": "Wrapped Ether", "symbol": "WETH", "decimals": 18, - "address": "0x51E83b811930bb4a3aAb3494894ec237Cb6cEc49" + "address": "0xDbEBD56A3068c71f6F71973171c6880a238Ff742" } ] diff --git a/l2-contracts/contracts/dev-contracts/DevL2SharedBridge.sol b/l2-contracts/contracts/dev-contracts/DevL2SharedBridge.sol index e93d5c987..fda1c5932 100644 --- a/l2-contracts/contracts/dev-contracts/DevL2SharedBridge.sol +++ b/l2-contracts/contracts/dev-contracts/DevL2SharedBridge.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.24; +pragma solidity ^0.8.20; import {L2SharedBridge} from "../bridge/L2SharedBridge.sol"; import {L2StandardERC20} from "../bridge/L2StandardERC20.sol"; diff --git a/l2-contracts/contracts/dev-contracts/ITimestampAsserter.sol b/l2-contracts/contracts/dev-contracts/ITimestampAsserter.sol new file mode 100644 index 000000000..47d9ec103 --- /dev/null +++ b/l2-contracts/contracts/dev-contracts/ITimestampAsserter.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +interface ITimestampAsserter { + function assertTimestampInRange(uint256 start, uint256 end) external view; +} diff --git a/l2-contracts/contracts/dev-contracts/Multicall3.sol b/l2-contracts/contracts/dev-contracts/Multicall3.sol new file mode 100644 index 000000000..aaa8b8012 --- /dev/null +++ b/l2-contracts/contracts/dev-contracts/Multicall3.sol @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +/// @title Multicall3 +/// @notice Aggregate results from multiple function calls +/// @dev Multicall & Multicall2 backwards-compatible +/// @dev Aggregate methods are marked `payable` to save 24 gas per call +/// @author Michael Elliot +/// @author Joshua Levine +/// @author Nick Johnson +/// @author Andreas Bigger +/// @author Matt Solomon +contract Multicall3 { + // add this to be excluded from coverage report + function test() internal virtual {} + + struct Call { + address target; + bytes callData; + } + + struct Call3 { + address target; + bool allowFailure; + bytes callData; + } + + struct Call3Value { + address target; + bool allowFailure; + uint256 value; + bytes callData; + } + + struct Result { + bool success; + bytes returnData; + } + + /// @notice Backwards-compatible call aggregation with Multicall + /// @param calls An array of Call structs + /// @return blockNumber The block number where the calls were executed + /// @return returnData An array of bytes containing the responses + function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) { + blockNumber = block.number; + uint256 length = calls.length; + returnData = new bytes[](length); + Call calldata call; + for (uint256 i = 0; i < length; ) { + bool success; + call = calls[i]; + (success, returnData[i]) = call.target.call(call.callData); + require(success, "Multicall3: call failed"); + unchecked { + ++i; + } + } + } + + /// @notice Backwards-compatible with Multicall2 + /// @notice Aggregate calls without requiring success + /// @param requireSuccess If true, require all calls to succeed + /// @param calls An array of Call structs + /// @return returnData An array of Result structs + function tryAggregate( + bool requireSuccess, + Call[] calldata calls + ) public payable returns (Result[] memory returnData) { + uint256 length = calls.length; + returnData = new Result[](length); + Call calldata call; + for (uint256 i = 0; i < length; ) { + Result memory result = returnData[i]; + call = calls[i]; + (result.success, result.returnData) = call.target.call(call.callData); + if (requireSuccess) require(result.success, "Multicall3: call failed"); + unchecked { + ++i; + } + } + } + + /// @notice Backwards-compatible with Multicall2 + /// @notice Aggregate calls and allow failures using tryAggregate + /// @param calls An array of Call structs + /// @return blockNumber The block number where the calls were executed + /// @return blockHash The hash of the block where the calls were executed + /// @return returnData An array of Result structs + function tryBlockAndAggregate( + bool requireSuccess, + Call[] calldata calls + ) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { + blockNumber = block.number; + blockHash = blockhash(block.number); + returnData = tryAggregate(requireSuccess, calls); + } + + /// @notice Backwards-compatible with Multicall2 + /// @notice Aggregate calls and allow failures using tryAggregate + /// @param calls An array of Call structs + /// @return blockNumber The block number where the calls were executed + /// @return blockHash The hash of the block where the calls were executed + /// @return returnData An array of Result structs + function blockAndAggregate( + Call[] calldata calls + ) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { + (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls); + } + + /// @notice Aggregate calls, ensuring each returns success if required + /// @param calls An array of Call3 structs + /// @return returnData An array of Result structs + function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) { + uint256 length = calls.length; + returnData = new Result[](length); + Call3 calldata calli; + for (uint256 i = 0; i < length; ) { + Result memory result = returnData[i]; + calli = calls[i]; + (result.success, result.returnData) = calli.target.call(calli.callData); + assembly { + // Revert if the call fails and failure is not allowed + // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` + if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { + // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) + mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) + // set data offset + mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) + // set length of revert string + mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) + // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) + mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) + revert(0x00, 0x64) + } + } + unchecked { + ++i; + } + } + } + + /// @notice Aggregate calls with a msg value + /// @notice Reverts if msg.value is less than the sum of the call values + /// @param calls An array of Call3Value structs + /// @return returnData An array of Result structs + function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) { + uint256 valAccumulator; + uint256 length = calls.length; + returnData = new Result[](length); + Call3Value calldata calli; + for (uint256 i = 0; i < length; ) { + Result memory result = returnData[i]; + calli = calls[i]; + uint256 val = calli.value; + // Humanity will be a Type V Kardashev Civilization before this overflows - andreas + // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256 + unchecked { + valAccumulator += val; + } + (result.success, result.returnData) = calli.target.call{value: val}(calli.callData); + assembly { + // Revert if the call fails and failure is not allowed + // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` + if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { + // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) + mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) + // set data offset + mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) + // set length of revert string + mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) + // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) + mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) + revert(0x00, 0x84) + } + } + unchecked { + ++i; + } + } + // Finally, make sure the msg.value = SUM(call[0...i].value) + require(msg.value == valAccumulator, "Multicall3: value mismatch"); + } + + /// @notice Returns the block hash for the given block number + /// @param blockNumber The block number + function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) { + blockHash = blockhash(blockNumber); + } + + /// @notice Returns the block number + function getBlockNumber() public view returns (uint256 blockNumber) { + blockNumber = block.number; + } + + /// @notice Returns the block coinbase + function getCurrentBlockCoinbase() public view returns (address coinbase) { + coinbase = block.coinbase; + } + + /// @notice Returns the block difficulty + function getCurrentBlockDifficulty() public view returns (uint256 difficulty) { + difficulty = block.prevrandao; + } + + /// @notice Returns the block gas limit + function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) { + gaslimit = block.gaslimit; + } + + /// @notice Returns the block timestamp + function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { + timestamp = block.timestamp; + } + + /// @notice Returns the (ETH) balance of a given address + function getEthBalance(address addr) public view returns (uint256 balance) { + balance = addr.balance; + } + + /// @notice Returns the block hash of the last block + function getLastBlockHash() public view returns (bytes32 blockHash) { + unchecked { + blockHash = blockhash(block.number - 1); + } + } + + /// @notice Gets the base fee of the given block + /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain + function getBasefee() public view returns (uint256 basefee) { + basefee = block.basefee; + } + + /// @notice Returns the chain id + function getChainId() public view returns (uint256 chainid) { + chainid = block.chainid; + } +} diff --git a/l2-contracts/contracts/dev-contracts/TimestampAsserter.sol b/l2-contracts/contracts/dev-contracts/TimestampAsserter.sol new file mode 100644 index 000000000..445313fe0 --- /dev/null +++ b/l2-contracts/contracts/dev-contracts/TimestampAsserter.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ITimestampAsserter} from "./ITimestampAsserter.sol"; + +error TimestampOutOfRange(uint256 currentTimestamp, uint256 start, uint256 end); + +/// @title TimestampAsserter +/// @author Matter Labs +/// @custom:security-contact security@matterlabs.dev +/// @dev A contract that verifies if the current block timestamp falls within a specified range. +/// This is useful for custom account abstraction where time-bound checks are needed but accessing block.timestamp +/// directly is not possible. +contract TimestampAsserter is ITimestampAsserter { + function assertTimestampInRange(uint256 _start, uint256 _end) external view { + if (block.timestamp < _start || block.timestamp > _end) { + revert TimestampOutOfRange(block.timestamp, _start, _end); + } + } +} diff --git a/l2-contracts/foundry.toml b/l2-contracts/foundry.toml index deb178a12..7fb4971c7 100644 --- a/l2-contracts/foundry.toml +++ b/l2-contracts/foundry.toml @@ -10,4 +10,4 @@ remappings = [ ] [profile.default.zksync] -zksolc = "1.5.0" +zksolc = "1.5.6" diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index a1ee58c12..14502f82b 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -1,233 +1,247 @@ [ { "contractName": "AccountCodeStorage", - "bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json", + "bytecodePath": "zkout/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x01000077e38f3e974a8def22f43e6c3c566d7c18ba04a55dfbad90dfd972920b", + "bytecodeHash": "0x010000771fe52d0c3549739647ab6e8f375522a1db0188c2bd817337e4f97a21", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", - "bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json", + "bytecodePath": "zkout/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f1264905c7690fec8739ef464fb0efe1b6a2b3d1ef9c8bc31021c2d3eb", + "bytecodeHash": "0x010006f18933c40f61d00c5d3d7cd62a6a4e5f43a570e8406968cebca58c9cee", "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", - "bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json", + "bytecodePath": "zkout/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x0100004781f95009a16d912d2bf05573968ed0897b590791129e5c8cd6a66257", + "bytecodeHash": "0x01000047a02183424005c945aaa56508fa915e0fc456b5af2b3a69fb511c9986", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", - "bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json", + "bytecodePath": "zkout/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013f94deb4d671b1f75987670fe3f875e0730aee2e4ae44d75f147201e38", + "bytecodeHash": "0x0100013f93ff6c87529264ab6f849af9e3d8501b236a6cd329f7c5eed13d89f0", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", - "bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json", + "bytecodePath": "zkout/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x0100067112f5b7b010c31dc21efe07f983df32f1908a48bd7084e8c967f19470", + "bytecodeHash": "0x010006713afcd2083d2511fb8e0b4ff6aa1f4a6f4ac52e93382b352a23196834", "sourceCodeHash": "0x3a03e66288c63fb72abe909ae829fa9495dce051753687d4395d41971847826b" }, { "contractName": "Create2Factory", - "bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json", + "bytecodePath": "zkout/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003f93af5076860d7d80073c61d1f81a2b41b685d139f17320e337dc204c", + "bytecodeHash": "0x0100003f4a41044ce23b381f86c0bdae97386a6af7427d0abdf23257c473591f", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", - "bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json", + "bytecodePath": "zkout/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100050989d91484a0d994fab1527c01f1f5fa39c9993945ae943874c4667e7d", + "bytecodeHash": "0x01000509541bc77ac7b80bffca30d1f055e23444d1eef75237cdad33d9640a65", "sourceCodeHash": "0xef448fac6b6f1c217b6495ee134a3553e02dfb920fd46bc71de33672e64d9ab8" }, { "contractName": "EmptyContract", - "bytecodePath": "artifacts-zk/contracts-preprocessed/EmptyContract.sol/EmptyContract.json", + "bytecodePath": "zkout/EmptyContract.sol/EmptyContract.json", "sourceCodePath": "contracts-preprocessed/EmptyContract.sol", - "bytecodeHash": "0x01000007947dfd1aab45b52e5998b442bfbd4d565af494fb8082a810c6ed0b50", + "bytecodeHash": "0x01000007150d65a7f607873013a4241fc90ae6357cc061983c2615f369d7ec56", "sourceCodeHash": "0xcac36c5afafbcff83601f4fbfdff660aa66d8c80ed97b9322d3011c1926b554d" }, { "contractName": "ImmutableSimulator", - "bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json", + "bytecodePath": "zkout/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033de8aeec22172e554f130cf986fc38c7c2d1fa0021d2197db9043b125", + "bytecodeHash": "0x0100003399fcfebcf86405f3042d660ac10035046f54053206aed71bc79deebe", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", - "bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json", + "bytecodePath": "zkout/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cdf509accfddca2517ef4a7ef699d898262af5e79f0e7c5c7966f12c6a", + "bytecodeHash": "0x010000cdf16e2bc07f27fe381c07118a8dc74af8057aa405a8fef6abc45276cb", "sourceCodeHash": "0x851fb5e170dfde39f1f9bc74654ec0b8f8f1d4c2fb20c06c77844c1e3ee0659a" }, { "contractName": "L1Messenger", - "bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json", + "bytecodePath": "zkout/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x010002659014fddc66937d91a9a4b149568ad0c7f6c3797ae7d5bd2a8ddd7877", + "bytecodeHash": "0x010002654afa780e927e7480444952e64e4fbc1ae6c4e213c6f012a230d9d540", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", - "bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json", + "bytecodePath": "zkout/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000f3e13f08f85a3271fb8bc1bf70364933b63e9d7025f722d98bc589e9d0", - "sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa" + "bytecodeHash": "0x010000db21d61724e8661c3408695636966e31fd804b04adb0c9a4d6c6bba805", + "sourceCodeHash": "0xdea518b1ea16718b0f0ec6155b227a8bc8f51374a9eebf7bc17cfe84433df740" }, { "contractName": "MsgValueSimulator", - "bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json", + "bytecodePath": "zkout/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005978b4f9317489d511739a80bedb832092c8741a45ed636de64167aca0", + "bytecodeHash": "0x0100005981495abcb1cb1cd8255d8e6638d44feba1ce7b492428c68890c76bdb", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", - "bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json", + "bytecodePath": "zkout/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cfa3b3ba69935156cb43bc4501fef0897c657dd0e5574064cad3243df0", + "bytecodeHash": "0x010000cffe86563fef453fc3d3b6fd4ce64b833c8c3e543348727c2128d92b78", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", - "bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", + "bytecodePath": "zkout/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041332bbd6c2abad4bc30bb3d9a9a26d914c11e4bcc803cd0905eaff964", + "bytecodeHash": "0x01000041d737da26e9cd50e031b84841f7a5e46a7577c9192e185a936538309d", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", - "bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json", + "bytecodePath": "zkout/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c5415782e13f8c4026d2b1e3270b4c5ef92fb9fe731ff2a3c1ada12601", + "bytecodeHash": "0x010001c5586ccbd00914acc256e20f4c401afce55cf5977c42de51fac1ece58e", "sourceCodeHash": "0xe2f6eb015d260aafe9405b28ef3ec27921add4de7f329b7ef61e0aa6c9365e29" }, { "contractName": "EventWriter", - "bytecodePath": "contracts-preprocessed/artifacts/EventWriter.yul/EventWriter.yul.zbin", + "bytecodePath": "zkout/EventWriter.yul/contracts-preprocessed/EventWriter.yul.json", "sourceCodePath": "contracts-preprocessed/EventWriter.yul", "bytecodeHash": "0x0100001739ee6f13091800b6cac4bd0c2c81dd81b449b6ddf3e663ce098c60ad", "sourceCodeHash": "0xfcf4828bcc109dea5f88c38f428d9ac5e18d5a2767fa4909277802c7e38c1f93" }, { "contractName": "EvmEmulator", - "bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin", + "bytecodePath": "zkout/EvmEmulator.yul/contracts-preprocessed/EvmEmulator.yul.json", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000cb5ab96098493fa599effb19ce9c6d8db6e9bfe34004ce3ff35e2225a75", + "bytecodeHash": "0x01000c070693d072058711a75fc0be958972d87e902cbce0fb7540ad24d2d367", "sourceCodeHash": "0x86296ecb81fc9edf5aac32613dfd645b538535e264e02a12ec7cdc751018de5d" }, { "contractName": "EvmGasManager", - "bytecodePath": "contracts-preprocessed/artifacts/EvmGasManager.yul/EvmGasManager.yul.zbin", + "bytecodePath": "zkout/EvmGasManager.yul/contracts-preprocessed/EvmGasManager.yul.json", "sourceCodePath": "contracts-preprocessed/EvmGasManager.yul", "bytecodeHash": "0x01000073f07635332a31f5a0f84ae277e3462b0240ced32b9def9785c67e6a99", "sourceCodeHash": "0x825dc1d9bec5128457a8b96eaf7ebf7c89dbb95a9bd7aab0f1601bc06455abfb" }, { "contractName": "CodeOracle", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/CodeOracle.yul/CodeOracle.yul.zbin", + "bytecodePath": "zkout/CodeOracle.yul/contracts-preprocessed/precompiles/CodeOracle.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/CodeOracle.yul", "bytecodeHash": "0x01000023e6a0f618c73d49c0ef7f231343b2d82b35d0f3048c2fad6fd6efaccb", "sourceCodeHash": "0xf4b21b6712a6e2a001a1b8214ac15959e670bd0ff125984486a28e128cb8846d" }, { "contractName": "EcAdd", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcAdd.yul/EcAdd.yul.zbin", + "bytecodePath": "zkout/EcAdd.yul/contracts-preprocessed/precompiles/EcAdd.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/EcAdd.yul", "bytecodeHash": "0x01000085f63553694e753270541123b5e2c2b809f1b883db3ceb830366524a40", "sourceCodeHash": "0xdfec1c5f8c6a93df1c8821f1ac15058a18a640bcbdeb67dc4a017f2153ff1c86" }, { "contractName": "EcMul", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcMul.yul/EcMul.yul.zbin", + "bytecodePath": "zkout/EcMul.yul/contracts-preprocessed/precompiles/EcMul.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/EcMul.yul", "bytecodeHash": "0x010000bbf677d3be4dbbf5dad75e63e87f2b1baf1b457d2507cb58025e26a2bf", "sourceCodeHash": "0x0e3f320c8a9532425b85809bf0a2136e707046a01bf20491ec03c77887516c43" }, { "contractName": "EcPairing", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/EcPairing.yul/EcPairing.yul.zbin", + "bytecodePath": "zkout/EcPairing.yul/contracts-preprocessed/precompiles/EcPairing.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/EcPairing.yul", "bytecodeHash": "0x01000ef38d94382bae33b3ffc36660e56b2df54c49c32963f49153830c36121e", "sourceCodeHash": "0x5d008cedc44e0e52c2567fd2b877916b2ec5e7c80294cf99b66485e50a6f2c12" }, { "contractName": "Ecrecover", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Ecrecover.yul/Ecrecover.yul.zbin", + "bytecodePath": "zkout/Ecrecover.yul/contracts-preprocessed/precompiles/Ecrecover.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/Ecrecover.yul", "bytecodeHash": "0x01000013ffc212bb76a7b9108abff6be1d0746154e36d32e9c69268ef95e556a", "sourceCodeHash": "0x21e03ab7a5f518a21258669c82506b1d4d1141f8fd4f30bb385f9730580ddd3c" }, { "contractName": "Identity", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Identity.yul/Identity.yul.zbin", + "bytecodePath": "zkout/Identity.yul/contracts-preprocessed/precompiles/Identity.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/Identity.yul", "bytecodeHash": "0x0100000d3cc11217da589db87c1cb3fda76701b7923b334b465eafd2e018b1b1", "sourceCodeHash": "0xcdf59308c83593ed41d9742411fdf41cfd9863932f948d20d08a11f6dcbd8f46" }, { "contractName": "Keccak256", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/Keccak256.yul/Keccak256.yul.zbin", + "bytecodePath": "zkout/Keccak256.yul/contracts-preprocessed/precompiles/Keccak256.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/Keccak256.yul", "bytecodeHash": "0x0100000f16ef9261284d26f08a560cd482ff7eb7944fe37ac99113aa4eb75188", "sourceCodeHash": "0xb454e7760732ce1fffc75174c8cf54dca422206cf1e52a29d274b310b574f26d" }, { "contractName": "P256Verify", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/P256Verify.yul/P256Verify.yul.zbin", + "bytecodePath": "zkout/P256Verify.yul/contracts-preprocessed/precompiles/P256Verify.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/P256Verify.yul", "bytecodeHash": "0x0100000ff914846f07b729f21be741f039c13d9c8e7c53e4db3a4c9a9f7e022d", "sourceCodeHash": "0x976b68d0362307313fd1aaea309eaa2d849187f37da451618c70dd3a6ac3cf3c" }, { "contractName": "SHA256", - "bytecodePath": "contracts-preprocessed/precompiles/artifacts/SHA256.yul/SHA256.yul.zbin", + "bytecodePath": "zkout/SHA256.yul/contracts-preprocessed/precompiles/SHA256.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/SHA256.yul", "bytecodeHash": "0x01000017cac2faad1aa8a1fd865fa464fbf092dbd8031dedb52fa6b8632e5b97", "sourceCodeHash": "0xfd4290467e26e992f39db9ca132e78ce99ce042b0254a368f1d7832dc94ddefb" }, { "contractName": "bootloader_test", - "bytecodePath": "bootloader/build/artifacts/bootloader_test.yul/bootloader_test.yul.zbin", + "bytecodePath": "zkout/bootloader_test.yul/contracts-preprocessed/bootloader/bootloader_test.yul.json", "sourceCodePath": "bootloader/build/bootloader_test.yul", "bytecodeHash": "0x010003adf0d7654575286de7e85d6ceb7572ca71498e5708313a9e9b3d7918e1", "sourceCodeHash": "0x4cac84261775ca327cf22d8b7595e020d03415e7c13311a8601b81543da1d94d" }, + { + "contractName": "dummy", + "bytecodePath": "zkout/dummy.yul/contracts-preprocessed/bootloader/dummy.yul.json", + "sourceCodePath": "bootloader/build/dummy.yul", + "bytecodeHash": "0x01000007b6aafb589f3b3d53466cb263cb237e75169fba7ba728aba0134007f9", + "sourceCodeHash": "0xfac5ca11a9882425af93fe5bac6d10055b119cf13af79e6a2f4e74e8411b9c85" + }, { "contractName": "fee_estimate", - "bytecodePath": "bootloader/build/artifacts/fee_estimate.yul/fee_estimate.yul.zbin", + "bytecodePath": "zkout/fee_estimate.yul/contracts-preprocessed/bootloader/fee_estimate.yul.json", "sourceCodePath": "bootloader/build/fee_estimate.yul", "bytecodeHash": "0x010008fd08bbea54c1315eb3e83d04f4fe3807d86b6e07a57e1bc22006a1aeda", "sourceCodeHash": "0xaa1836b407eae63dcac7b99cfb91defdbac7baa6f4c049f9118181fff58c37ec" }, { "contractName": "gas_test", - "bytecodePath": "bootloader/build/artifacts/gas_test.yul/gas_test.yul.zbin", + "bytecodePath": "zkout/gas_test.yul/contracts-preprocessed/bootloader/gas_test.yul.json", "sourceCodePath": "bootloader/build/gas_test.yul", "bytecodeHash": "0x0100086956002b1d347b18a1a4b6d0cbb6136afc0a3cf6cd4371bf087caec0e5", "sourceCodeHash": "0x8c224e2e3c6e7c516ce5fbbbe841ecaaeb239e15e24ac0f2f7b4a8a11e9d9dfa" }, { "contractName": "playground_batch", - "bytecodePath": "bootloader/build/artifacts/playground_batch.yul/playground_batch.yul.zbin", + "bytecodePath": "zkout/playground_batch.yul/contracts-preprocessed/bootloader/playground_batch.yul.json", "sourceCodePath": "bootloader/build/playground_batch.yul", "bytecodeHash": "0x01000903ffd673549dcae99cd0f01a33fc5679fa600084f084179f9cbe7bf506", "sourceCodeHash": "0x04d534fd13610e0a82531f4d2a466e5b6caf814a50fb3a1b0f7d77918f078d26" }, { "contractName": "proved_batch", - "bytecodePath": "bootloader/build/artifacts/proved_batch.yul/proved_batch.yul.zbin", + "bytecodePath": "zkout/proved_batch.yul/contracts-preprocessed/bootloader/proved_batch.yul.json", "sourceCodePath": "bootloader/build/proved_batch.yul", "bytecodeHash": "0x0100087b232b86e32e87f8acfb75c98a50363eb7ccbe504aae3f7b7e8dd94dbf", "sourceCodeHash": "0x72564482cf4e0e31bd47dbd15729952dd6994508c06f5065c2106920ad8e5a33" + }, + { + "contractName": "transfer_test", + "bytecodePath": "zkout/transfer_test.yul/contracts-preprocessed/bootloader/transfer_test.yul.json", + "sourceCodePath": "bootloader/build/transfer_test.yul", + "bytecodeHash": "0x0100001532ccf5b061252699f6d2c677d987c775f48152271d5be4f02e41e454", + "sourceCodeHash": "0xb828600c6f7366971580b68da39c3e449b9a0f922f52dd9841f33ae7f51ee71c" } ] diff --git a/system-contracts/contracts/L2BaseToken.sol b/system-contracts/contracts/L2BaseToken.sol index 9f826a80b..d7a047a8f 100644 --- a/system-contracts/contracts/L2BaseToken.sol +++ b/system-contracts/contracts/L2BaseToken.sol @@ -127,22 +127,4 @@ contract L2BaseToken is IBaseToken, SystemContractBase { // solhint-disable-next-line func-named-parameters return abi.encodePacked(IMailbox.finalizeEthWithdrawal.selector, _to, _amount, _sender, _additionalData); } - - /// @dev This method has not been stabilized and might be - /// removed later on. - function name() external pure override returns (string memory) { - return "Ether"; - } - - /// @dev This method has not been stabilized and might be - /// removed later on. - function symbol() external pure override returns (string memory) { - return "ETH"; - } - - /// @dev This method has not been stabilized and might be - /// removed later on. - function decimals() external pure override returns (uint8) { - return 18; - } } diff --git a/system-contracts/contracts/interfaces/IBaseToken.sol b/system-contracts/contracts/interfaces/IBaseToken.sol index fc32c7b83..2bd15be51 100644 --- a/system-contracts/contracts/interfaces/IBaseToken.sol +++ b/system-contracts/contracts/interfaces/IBaseToken.sol @@ -9,12 +9,6 @@ interface IBaseToken { function totalSupply() external view returns (uint256); - function name() external pure returns (string memory); - - function symbol() external pure returns (string memory); - - function decimals() external pure returns (uint8); - function mint(address _account, uint256 _amount) external; function withdraw(address _l1Receiver) external payable; diff --git a/system-contracts/foundry.toml b/system-contracts/foundry.toml index cfd793dac..5ccba6df0 100644 --- a/system-contracts/foundry.toml +++ b/system-contracts/foundry.toml @@ -12,4 +12,5 @@ remappings = [ [profile.default.zksync] zksolc = "1.5.6" +enable_eravm_extensions = true suppressed_errors = ["sendtransfer"] diff --git a/system-contracts/package.json b/system-contracts/package.json index 085dab5d2..c2bda4785 100644 --- a/system-contracts/package.json +++ b/system-contracts/package.json @@ -50,7 +50,7 @@ ] }, "scripts": { - "build": "yarn build:system-contracts && yarn build:bootloader", + "build": "yarn build:system-contracts && yarn build:bootloader && forge build --zksync", "build:bootloader": "yarn preprocess:bootloader && yarn compile-yul compile-bootloader", "build:system-contracts": "yarn preprocess:emulator && yarn preprocess:system-contracts && hardhat compile && yarn compile-yul compile-precompiles", "build:test-system-contracts": "yarn preprocess:system-contracts --test-mode && hardhat compile && yarn compile-yul compile-precompiles && yarn compile-zasm", diff --git a/system-contracts/scripts/calculate-hashes.ts b/system-contracts/scripts/calculate-hashes.ts index e63c3abf8..7ecb66723 100644 --- a/system-contracts/scripts/calculate-hashes.ts +++ b/system-contracts/scripts/calculate-hashes.ts @@ -42,10 +42,10 @@ const findFilesEndingWith = (path: string, endingWith: string): string[] => { } }; -const SOLIDITY_ARTIFACTS_DIR = "artifacts-zk"; +const SOLIDITY_ARTIFACTS_DIR = "zkout"; const getSolidityContractDetails = (dir: string, contractName: string): ContractDetails => { - const bytecodePath = join(SOLIDITY_ARTIFACTS_DIR, dir, contractName + ".sol", contractName + ".json"); + const bytecodePath = join(SOLIDITY_ARTIFACTS_DIR, contractName + ".sol", contractName + ".json"); const sourceCodePath = join(dir, contractName + ".sol"); return { contractName, @@ -55,17 +55,23 @@ const getSolidityContractDetails = (dir: string, contractName: string): Contract }; const getSolidityContractsDetails = (dir: string): ContractDetails[] => { - const bytecodesDir = join(SOLIDITY_ARTIFACTS_DIR, dir); + const absolutePath = makePathAbsolute(dir); + const eligibleFiles = fs + .readdirSync(absolutePath) + .filter((f) => f.endsWith(".sol")) + .map((f) => f.replace(".sol", "")); + const bytecodesDir = SOLIDITY_ARTIFACTS_DIR; const dirsEndingWithSol = findDirsEndingWith(bytecodesDir, ".sol"); - const contractNames = dirsEndingWithSol.map((d) => d.replace(".sol", "")); + const contractNames = dirsEndingWithSol.map((d) => d.replace(".sol", "")).filter((c) => eligibleFiles.includes(c)); const solidityContractsDetails = contractNames.map((c) => getSolidityContractDetails(dir, c)); return solidityContractsDetails; }; -const YUL_ARTIFACTS_DIR = "artifacts"; +const YUL_ARTIFACTS_DIR = "zkout"; const getYulContractDetails = (dir: string, contractName: string): ContractDetails => { - const bytecodePath = join(dir, YUL_ARTIFACTS_DIR, contractName + ".yul", contractName + ".yul.zbin"); + const artifactPath = dir !== "bootloader/build" ? dir : "contracts-preprocessed/bootloader"; + const bytecodePath = join(YUL_ARTIFACTS_DIR, contractName + ".yul", artifactPath, contractName + ".yul.json"); const sourceCodePath = join(dir, contractName + ".yul"); return { contractName, @@ -100,7 +106,7 @@ const readBytecode = (details: ContractDetails): string => { try { if (details.bytecodePath.endsWith(".json")) { const jsonFile = fs.readFileSync(absolutePath, "utf8"); - return ethers.utils.hexlify(JSON.parse(jsonFile).bytecode); + return ethers.utils.hexlify("0x" + JSON.parse(jsonFile).bytecode.object); } else { return ethers.utils.hexlify(fs.readFileSync(absolutePath).toString(), { allowMissingPrefix: true }); } diff --git a/system-contracts/scripts/preprocess-bootloader.ts b/system-contracts/scripts/preprocess-bootloader.ts index 952181455..e3dc18aaf 100644 --- a/system-contracts/scripts/preprocess-bootloader.ts +++ b/system-contracts/scripts/preprocess-bootloader.ts @@ -13,7 +13,8 @@ const preprocess = require("preprocess"); const SYSTEM_PARAMS = require("../../SystemConfig.json"); /* eslint-enable@typescript-eslint/no-var-requires */ -const OUTPUT_DIR = "bootloader/build"; +const OUTPUT_DIR_1 = "contracts-preprocessed/bootloader"; +const OUTPUT_DIR_2 = "bootloader/build"; const PREPROCCESING_MODES = ["proved_batch", "playground_batch"]; @@ -224,15 +225,32 @@ async function main() { }); const provedBootloaderWithTests = preprocess.preprocess(bootloaderWithTests, { BOOTLOADER_TYPE: "proved_batch" }); - if (!existsSync(OUTPUT_DIR)) { - mkdirSync(OUTPUT_DIR); + if (!existsSync(OUTPUT_DIR_1)) { + mkdirSync(OUTPUT_DIR_1); } - writeFileSync(`${OUTPUT_DIR}/bootloader_test.yul`, provedBootloaderWithTests); - writeFileSync(`${OUTPUT_DIR}/proved_batch.yul`, provedBatchBootloader); - writeFileSync(`${OUTPUT_DIR}/playground_batch.yul`, playgroundBatchBootloader); - writeFileSync(`${OUTPUT_DIR}/gas_test.yul`, gasTestBootloader); - writeFileSync(`${OUTPUT_DIR}/fee_estimate.yul`, feeEstimationBootloader); + if (!existsSync(OUTPUT_DIR_2)) { + mkdirSync(OUTPUT_DIR_2); + } + + const transferTest = readFileSync("bootloader/tests/transfer_test.yul").toString(); + const dummy = readFileSync("bootloader/tests/dummy.yul").toString(); + + writeFileSync(`${OUTPUT_DIR_1}/bootloader_test.yul`, provedBootloaderWithTests); + writeFileSync(`${OUTPUT_DIR_1}/proved_batch.yul`, provedBatchBootloader); + writeFileSync(`${OUTPUT_DIR_1}/playground_batch.yul`, playgroundBatchBootloader); + writeFileSync(`${OUTPUT_DIR_1}/gas_test.yul`, gasTestBootloader); + writeFileSync(`${OUTPUT_DIR_1}/fee_estimate.yul`, feeEstimationBootloader); + writeFileSync(`${OUTPUT_DIR_1}/dummy.yul`, dummy); + writeFileSync(`${OUTPUT_DIR_1}/transfer_test.yul`, transferTest); + + writeFileSync(`${OUTPUT_DIR_2}/bootloader_test.yul`, provedBootloaderWithTests); + writeFileSync(`${OUTPUT_DIR_2}/proved_batch.yul`, provedBatchBootloader); + writeFileSync(`${OUTPUT_DIR_2}/playground_batch.yul`, playgroundBatchBootloader); + writeFileSync(`${OUTPUT_DIR_2}/gas_test.yul`, gasTestBootloader); + writeFileSync(`${OUTPUT_DIR_2}/fee_estimate.yul`, feeEstimationBootloader); + writeFileSync(`${OUTPUT_DIR_2}/dummy.yul`, dummy); + writeFileSync(`${OUTPUT_DIR_2}/transfer_test.yul`, transferTest); console.log("Bootloader preprocessing done!"); } diff --git a/system-contracts/test/L2BaseToken.spec.ts b/system-contracts/test/L2BaseToken.spec.ts index d73f0444d..f4d9c5c92 100644 --- a/system-contracts/test/L2BaseToken.spec.ts +++ b/system-contracts/test/L2BaseToken.spec.ts @@ -146,27 +146,6 @@ describe("L2BaseToken tests", () => { }); }); - describe("name", () => { - it("correct name", async () => { - const name = await L2BaseToken.name(); - expect(name).to.equal("Ether"); - }); - }); - - describe("symbol", () => { - it("correct symbol", async () => { - const symbol = await L2BaseToken.symbol(); - expect(symbol).to.equal("ETH"); - }); - }); - - describe("decimals", () => { - it("correct decimals", async () => { - const decimals = await L2BaseToken.decimals(); - expect(decimals).to.equal(18); - }); - }); - describe("withdraw", () => { it("event, balance, totalsupply", async () => { const amountToWithdraw: BigNumber = ethers.utils.parseEther("1.0"); From ca3f1356060092605045496c9aeb32229a55d1c8 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 20 Nov 2024 15:17:51 +0100 Subject: [PATCH 141/183] Fix hashes --- system-contracts/SystemContractsHashes.json | 68 ++++++++++----------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 61193ca40..14502f82b 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,113 +3,113 @@ "contractName": "AccountCodeStorage", "bytecodePath": "zkout/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x01000059e58c4b510c6d3000e492d1c98cf6f5e97b17485d2fd4ae20774bbe31", - "sourceCodeHash": "0x2e0e09d57a04bd1e722d8bf8c6423fdf3f8bca44e5e8c4f6684f987794be066e" + "bytecodeHash": "0x010000771fe52d0c3549739647ab6e8f375522a1db0188c2bd817337e4f97a21", + "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "zkout/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006dff879b6fda1310d6f6bacb5188744476796e0e78b8ef0f3665d221f64", - "sourceCodeHash": "0x0f1213c4b95acb71f4ab5d4082cc1aeb2bd5017e1cccd46afc66e53268609d85" + "bytecodeHash": "0x010006f18933c40f61d00c5d3d7cd62a6a4e5f43a570e8406968cebca58c9cee", + "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" }, { "contractName": "ComplexUpgrader", "bytecodePath": "zkout/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x010000477573dcfd9cf37d44859d54b7b176acba85ae8f18fd5ace0308d6f0ec", + "bytecodeHash": "0x01000047a02183424005c945aaa56508fa915e0fc456b5af2b3a69fb511c9986", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "zkout/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013f2d65426f271606752ad9ece505c728b90377406aa46cef48e611fa1f", + "bytecodeHash": "0x0100013f93ff6c87529264ab6f849af9e3d8501b236a6cd329f7c5eed13d89f0", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "zkout/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x0100042d3e0b1d7027c7095a48fbac09515ee2417407678e237c0d29a4fbf7c2", - "sourceCodeHash": "0x82f81fbf5fb007a9cac97462d50907ca5d7a1af62d82d2645e093ed8647a5209" + "bytecodeHash": "0x010006713afcd2083d2511fb8e0b4ff6aa1f4a6f4ac52e93382b352a23196834", + "sourceCodeHash": "0x3a03e66288c63fb72abe909ae829fa9495dce051753687d4395d41971847826b" }, { "contractName": "Create2Factory", "bytecodePath": "zkout/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003f1e5d0e280c87a85625b19e23840538c0fee2adb6f473ae7deda99666", + "bytecodeHash": "0x0100003f4a41044ce23b381f86c0bdae97386a6af7427d0abdf23257c473591f", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "zkout/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x010004dbe4df43333285d1984685bdb9aec3044931473c777483d63a99e66bb9", - "sourceCodeHash": "0xebffe840ebbd9329edb1ebff8ca50f6935e7dabcc67194a896fcc2e968d46dfb" + "bytecodeHash": "0x01000509541bc77ac7b80bffca30d1f055e23444d1eef75237cdad33d9640a65", + "sourceCodeHash": "0xef448fac6b6f1c217b6495ee134a3553e02dfb920fd46bc71de33672e64d9ab8" }, { "contractName": "EmptyContract", "bytecodePath": "zkout/EmptyContract.sol/EmptyContract.json", "sourceCodePath": "contracts-preprocessed/EmptyContract.sol", - "bytecodeHash": "0x0100000759fbd07e0d0781d79416d24706955ba013862ffdd9c45d429d474784", + "bytecodeHash": "0x01000007150d65a7f607873013a4241fc90ae6357cc061983c2615f369d7ec56", "sourceCodeHash": "0xcac36c5afafbcff83601f4fbfdff660aa66d8c80ed97b9322d3011c1926b554d" }, { "contractName": "ImmutableSimulator", "bytecodePath": "zkout/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000035b6bcb201f45b122be5632b55de78374a18efb2b812c943c3ee9ad154", + "bytecodeHash": "0x0100003399fcfebcf86405f3042d660ac10035046f54053206aed71bc79deebe", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "zkout/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000692d7c6660a194c9128f937fcf638a3309424fa90d8e25107b76928d40", - "sourceCodeHash": "0xb39b5b81168653e0c5062f7b8e1d6d15a4e186df3317f192f0cb2fc3a74f5448" + "bytecodeHash": "0x010000cdf16e2bc07f27fe381c07118a8dc74af8057aa405a8fef6abc45276cb", + "sourceCodeHash": "0x851fb5e170dfde39f1f9bc74654ec0b8f8f1d4c2fb20c06c77844c1e3ee0659a" }, { "contractName": "L1Messenger", "bytecodePath": "zkout/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000261fc2f8bc373116ad7adab8fe9022996cf866f4eecf81034a7ad2ef357", + "bytecodeHash": "0x010002654afa780e927e7480444952e64e4fbc1ae6c4e213c6f012a230d9d540", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "zkout/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000ddd98f7915c8d5f04c9011f301b9714b10cd3c9d30f89d93c29d3dd3a7", + "bytecodeHash": "0x010000db21d61724e8661c3408695636966e31fd804b04adb0c9a4d6c6bba805", "sourceCodeHash": "0xdea518b1ea16718b0f0ec6155b227a8bc8f51374a9eebf7bc17cfe84433df740" }, { "contractName": "MsgValueSimulator", "bytecodePath": "zkout/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005990ed517bc98ec25743f96de6d45efccce22b32a81093a10ba2e0eab5", + "bytecodeHash": "0x0100005981495abcb1cb1cd8255d8e6638d44feba1ce7b492428c68890c76bdb", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "zkout/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000d1e115f2aef2379c5544d8484268e305a60871d658b7af0be1870d3ac0", + "bytecodeHash": "0x010000cffe86563fef453fc3d3b6fd4ce64b833c8c3e543348727c2128d92b78", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "zkout/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041bfabdaaca186f9dc45a63b51be68d169c295b738788bc26f59370281", + "bytecodeHash": "0x01000041d737da26e9cd50e031b84841f7a5e46a7577c9192e185a936538309d", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "zkout/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a5ede6eafde755e1630fd4b287ad382955fa0339cb1f0bef5d35f858a7", - "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" + "bytecodeHash": "0x010001c5586ccbd00914acc256e20f4c401afce55cf5977c42de51fac1ece58e", + "sourceCodeHash": "0xe2f6eb015d260aafe9405b28ef3ec27921add4de7f329b7ef61e0aa6c9365e29" }, { "contractName": "EventWriter", @@ -136,8 +136,8 @@ "contractName": "CodeOracle", "bytecodePath": "zkout/CodeOracle.yul/contracts-preprocessed/precompiles/CodeOracle.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/CodeOracle.yul", - "bytecodeHash": "0x010000210cd0b1ab22d71e01091a15cb8190e30d884784b092640d83aaf6c462", - "sourceCodeHash": "0x476063e7907f2b7a532c4da6f606fa07186b5a10d77af8fdd83dbea3d9f23f93" + "bytecodeHash": "0x01000023e6a0f618c73d49c0ef7f231343b2d82b35d0f3048c2fad6fd6efaccb", + "sourceCodeHash": "0xf4b21b6712a6e2a001a1b8214ac15959e670bd0ff125984486a28e128cb8846d" }, { "contractName": "EcAdd", @@ -199,8 +199,8 @@ "contractName": "bootloader_test", "bytecodePath": "zkout/bootloader_test.yul/contracts-preprocessed/bootloader/bootloader_test.yul.json", "sourceCodePath": "bootloader/build/bootloader_test.yul", - "bytecodeHash": "0x010003ade02adac2c039832861a6649c6cbb7abbb2ff8542c6aefff7bde06a9c", - "sourceCodeHash": "0x006fdf461899dec5fdb34301c23e6819eb93e275907cbfc67d73fccfb47cae68" + "bytecodeHash": "0x010003adf0d7654575286de7e85d6ceb7572ca71498e5708313a9e9b3d7918e1", + "sourceCodeHash": "0x4cac84261775ca327cf22d8b7595e020d03415e7c13311a8601b81543da1d94d" }, { "contractName": "dummy", @@ -213,29 +213,29 @@ "contractName": "fee_estimate", "bytecodePath": "zkout/fee_estimate.yul/contracts-preprocessed/bootloader/fee_estimate.yul.json", "sourceCodePath": "bootloader/build/fee_estimate.yul", - "bytecodeHash": "0x01000905327a3aeb212816e7e0f6c16c5acc491c714c06d823c4bbc7075b62d6", - "sourceCodeHash": "0x8a858319bac2924a3dee778218a7fe5e23898db0d87b02d7b783f94c5a02d257" + "bytecodeHash": "0x010008fd08bbea54c1315eb3e83d04f4fe3807d86b6e07a57e1bc22006a1aeda", + "sourceCodeHash": "0xaa1836b407eae63dcac7b99cfb91defdbac7baa6f4c049f9118181fff58c37ec" }, { "contractName": "gas_test", "bytecodePath": "zkout/gas_test.yul/contracts-preprocessed/bootloader/gas_test.yul.json", "sourceCodePath": "bootloader/build/gas_test.yul", - "bytecodeHash": "0x01000871cdb46e23c5b65176cd772e368d255c80290058b89e9644efbe8d7c53", - "sourceCodeHash": "0x89f5ad470f10e755fa57b82507518e571c24409a328bc33aeba26e9518ad1c3e" + "bytecodeHash": "0x0100086956002b1d347b18a1a4b6d0cbb6136afc0a3cf6cd4371bf087caec0e5", + "sourceCodeHash": "0x8c224e2e3c6e7c516ce5fbbbe841ecaaeb239e15e24ac0f2f7b4a8a11e9d9dfa" }, { "contractName": "playground_batch", "bytecodePath": "zkout/playground_batch.yul/contracts-preprocessed/bootloader/playground_batch.yul.json", "sourceCodePath": "bootloader/build/playground_batch.yul", - "bytecodeHash": "0x01000909408f87054598e7a1e9fbc58e0e9733b0ab5030618eef36ef746cac68", - "sourceCodeHash": "0x769448c4fd2b65c43d758ca5f34dd29d9b9dd3000fd0ec89cffcaf8d365a64fd" + "bytecodeHash": "0x01000903ffd673549dcae99cd0f01a33fc5679fa600084f084179f9cbe7bf506", + "sourceCodeHash": "0x04d534fd13610e0a82531f4d2a466e5b6caf814a50fb3a1b0f7d77918f078d26" }, { "contractName": "proved_batch", "bytecodePath": "zkout/proved_batch.yul/contracts-preprocessed/bootloader/proved_batch.yul.json", "sourceCodePath": "bootloader/build/proved_batch.yul", - "bytecodeHash": "0x01000881f046342b70470a7e81423b5903dfe06669d01292e7dc6f8eb73bf404", - "sourceCodeHash": "0x908bc6ddb34ef89b125e9637239a1149deacacd91255781d82a65a542a39036e" + "bytecodeHash": "0x0100087b232b86e32e87f8acfb75c98a50363eb7ccbe504aae3f7b7e8dd94dbf", + "sourceCodeHash": "0x72564482cf4e0e31bd47dbd15729952dd6994508c06f5065c2106920ad8e5a33" }, { "contractName": "transfer_test", From d1d4391b7d4685346d005df75935769a42ea60bc Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 20 Nov 2024 18:46:26 +0100 Subject: [PATCH 142/183] feat: Bump zksolc to 1.5.7 (#1076) --- l2-contracts/foundry.toml | 2 +- l2-contracts/hardhat.config.ts | 2 +- system-contracts/SystemContractsHashes.json | 64 ++++++++++----------- system-contracts/foundry.toml | 2 +- system-contracts/hardhat.config.ts | 18 +----- system-contracts/scripts/compile-yul.ts | 4 +- system-contracts/scripts/compile-zasm.ts | 4 +- 7 files changed, 40 insertions(+), 56 deletions(-) diff --git a/l2-contracts/foundry.toml b/l2-contracts/foundry.toml index 7fb4971c7..5e7be2051 100644 --- a/l2-contracts/foundry.toml +++ b/l2-contracts/foundry.toml @@ -10,4 +10,4 @@ remappings = [ ] [profile.default.zksync] -zksolc = "1.5.6" +zksolc = "1.5.7" diff --git a/l2-contracts/hardhat.config.ts b/l2-contracts/hardhat.config.ts index 282ab7b96..3e05a558a 100644 --- a/l2-contracts/hardhat.config.ts +++ b/l2-contracts/hardhat.config.ts @@ -12,7 +12,7 @@ if (!process.env.CHAIN_ETH_NETWORK) { export default { zksolc: { - version: "1.5.0", + version: "1.5.7", compilerSource: "binary", settings: { isSystem: true, diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 3404828fe..6204d7db4 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,224 +3,224 @@ "contractName": "AccountCodeStorage", "bytecodePath": "zkout/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x01000059e58c4b510c6d3000e492d1c98cf6f5e97b17485d2fd4ae20774bbe31", + "bytecodeHash": "0x01000059b17a0edb4b15b38ad4f1ff583f90e01623b4bf816890422657411820", "sourceCodeHash": "0x2e0e09d57a04bd1e722d8bf8c6423fdf3f8bca44e5e8c4f6684f987794be066e" }, { "contractName": "BootloaderUtilities", "bytecodePath": "zkout/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006dff879b6fda1310d6f6bacb5188744476796e0e78b8ef0f3665d221f64", + "bytecodeHash": "0x010006dfadf0602264b8bf7857d8503f81dad391df9d746ea6ecc09d153cfc70", "sourceCodeHash": "0x0f1213c4b95acb71f4ab5d4082cc1aeb2bd5017e1cccd46afc66e53268609d85" }, { "contractName": "ComplexUpgrader", "bytecodePath": "zkout/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x010000477573dcfd9cf37d44859d54b7b176acba85ae8f18fd5ace0308d6f0ec", + "bytecodeHash": "0x01000047006264894aaf02bdf6f621f40f57e3de7467059b514fe9cd55d1e612", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "zkout/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013f2d65426f271606752ad9ece505c728b90377406aa46cef48e611fa1f", + "bytecodeHash": "0x0100013f5bde1d3246e7dbb14d1a136a46831a64e6d657dabda2932fd62e2317", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "zkout/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x0100042d3e0b1d7027c7095a48fbac09515ee2417407678e237c0d29a4fbf7c2", + "bytecodeHash": "0x0100042d7de57aabc942f9a18373e396909775f5b8254dda6bed6370535478f4", "sourceCodeHash": "0x82f81fbf5fb007a9cac97462d50907ca5d7a1af62d82d2645e093ed8647a5209" }, { "contractName": "Create2Factory", "bytecodePath": "zkout/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003f1e5d0e280c87a85625b19e23840538c0fee2adb6f473ae7deda99666", + "bytecodeHash": "0x0100003f763825fe9f1a8e5f7a78f3bbb4e4d3c80bd0c0f29198277bb8667150", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "zkout/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x010004dbe4df43333285d1984685bdb9aec3044931473c777483d63a99e66bb9", + "bytecodeHash": "0x010004db5a3c4eda46acb1dae10a9c8bc71066fc9eeb32056ff68fb7e8a2a7e9", "sourceCodeHash": "0xebffe840ebbd9329edb1ebff8ca50f6935e7dabcc67194a896fcc2e968d46dfb" }, { "contractName": "EmptyContract", "bytecodePath": "zkout/EmptyContract.sol/EmptyContract.json", "sourceCodePath": "contracts-preprocessed/EmptyContract.sol", - "bytecodeHash": "0x0100000759fbd07e0d0781d79416d24706955ba013862ffdd9c45d429d474784", + "bytecodeHash": "0x01000007053231bb71767708c7c8b18bee3ce13af3f346352471809266e6ca8b", "sourceCodeHash": "0xcac36c5afafbcff83601f4fbfdff660aa66d8c80ed97b9322d3011c1926b554d" }, { "contractName": "ImmutableSimulator", "bytecodePath": "zkout/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000035b6bcb201f45b122be5632b55de78374a18efb2b812c943c3ee9ad154", + "bytecodeHash": "0x010000352a4c9cb410804df1e731568721b59cd77187d984682fe5208e18ad16", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "zkout/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000692d7c6660a194c9128f937fcf638a3309424fa90d8e25107b76928d40", + "bytecodeHash": "0x01000069bea7c438daaf61e5743c22c2dd6ff9180e2845727d4c5f995aab15a8", "sourceCodeHash": "0xb39b5b81168653e0c5062f7b8e1d6d15a4e186df3317f192f0cb2fc3a74f5448" }, { "contractName": "L1Messenger", "bytecodePath": "zkout/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000261fc2f8bc373116ad7adab8fe9022996cf866f4eecf81034a7ad2ef357", + "bytecodeHash": "0x0100026167ff1be1af4471d8992ceeb66902ef7a3c4148570b947d257ce3b923", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "zkout/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000ddd98f7915c8d5f04c9011f301b9714b10cd3c9d30f89d93c29d3dd3a7", + "bytecodeHash": "0x010000ddfd7eab80277672aa8cb37fdc5338f5034b8de9ffefb778ed6df4414a", "sourceCodeHash": "0xdea518b1ea16718b0f0ec6155b227a8bc8f51374a9eebf7bc17cfe84433df740" }, { "contractName": "MsgValueSimulator", "bytecodePath": "zkout/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005990ed517bc98ec25743f96de6d45efccce22b32a81093a10ba2e0eab5", + "bytecodeHash": "0x01000059783c42bcdc0ad44f4df48521854da0f47efc603dadcd0b47040c183d", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "zkout/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000d1e115f2aef2379c5544d8484268e305a60871d658b7af0be1870d3ac0", + "bytecodeHash": "0x010000d1b03fc58609492a125c429077e65a4f566af9dfebd899ad127122a234", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "zkout/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041bfabdaaca186f9dc45a63b51be68d169c295b738788bc26f59370281", + "bytecodeHash": "0x010000418f7a6ab81233720485c2ad728bdc23e2ad99068b149ecf19d111ac6e", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "zkout/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001a5ede6eafde755e1630fd4b287ad382955fa0339cb1f0bef5d35f858a7", + "bytecodeHash": "0x010001a5ebd43618bd4de33a36d21b78d216631fab1c92df914723a325b95d3b", "sourceCodeHash": "0xf308743981ef5cea2f7a3332b8e51695a5e47e811a63974437fc1cceee475e7a" }, { "contractName": "EventWriter", "bytecodePath": "zkout/EventWriter.yul/contracts-preprocessed/EventWriter.yul.json", "sourceCodePath": "contracts-preprocessed/EventWriter.yul", - "bytecodeHash": "0x0100001739ee6f13091800b6cac4bd0c2c81dd81b449b6ddf3e663ce098c60ad", + "bytecodeHash": "0x01000017575446d56eb4e640189c5e356449975b957ae5262924567f4f664d75", "sourceCodeHash": "0xfcf4828bcc109dea5f88c38f428d9ac5e18d5a2767fa4909277802c7e38c1f93" }, { "contractName": "CodeOracle", "bytecodePath": "zkout/CodeOracle.yul/contracts-preprocessed/precompiles/CodeOracle.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/CodeOracle.yul", - "bytecodeHash": "0x010000210cd0b1ab22d71e01091a15cb8190e30d884784b092640d83aaf6c462", + "bytecodeHash": "0x010000213ed880e87b5121c3d96a0cf6787ca83dda10080a1d7cce7ad72bf6a6", "sourceCodeHash": "0x476063e7907f2b7a532c4da6f606fa07186b5a10d77af8fdd83dbea3d9f23f93" }, { "contractName": "EcAdd", "bytecodePath": "zkout/EcAdd.yul/contracts-preprocessed/precompiles/EcAdd.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/EcAdd.yul", - "bytecodeHash": "0x01000085f63553694e753270541123b5e2c2b809f1b883db3ceb830366524a40", + "bytecodeHash": "0x01000085bf765ff04ad45979da71816fba3bdee901366c5cce73c94f3ee37bb9", "sourceCodeHash": "0xdfec1c5f8c6a93df1c8821f1ac15058a18a640bcbdeb67dc4a017f2153ff1c86" }, { "contractName": "EcMul", "bytecodePath": "zkout/EcMul.yul/contracts-preprocessed/precompiles/EcMul.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/EcMul.yul", - "bytecodeHash": "0x010000bbf677d3be4dbbf5dad75e63e87f2b1baf1b457d2507cb58025e26a2bf", + "bytecodeHash": "0x010000bbb84f463e70d100c271744ab9827d4c9b66ee4356a0c697dcb54e3b87", "sourceCodeHash": "0x0e3f320c8a9532425b85809bf0a2136e707046a01bf20491ec03c77887516c43" }, { "contractName": "EcPairing", "bytecodePath": "zkout/EcPairing.yul/contracts-preprocessed/precompiles/EcPairing.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/EcPairing.yul", - "bytecodeHash": "0x01000ef38d94382bae33b3ffc36660e56b2df54c49c32963f49153830c36121e", + "bytecodeHash": "0x01000ef37666c6447ad953d8be7ca75d4a0de3d5fd57a3966906d2c5577111ab", "sourceCodeHash": "0x5d008cedc44e0e52c2567fd2b877916b2ec5e7c80294cf99b66485e50a6f2c12" }, { "contractName": "Ecrecover", "bytecodePath": "zkout/Ecrecover.yul/contracts-preprocessed/precompiles/Ecrecover.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/Ecrecover.yul", - "bytecodeHash": "0x01000013ffc212bb76a7b9108abff6be1d0746154e36d32e9c69268ef95e556a", + "bytecodeHash": "0x01000013409fe778437b58e5819ee48a658fb09b86bb7badf93cb334c16cc632", "sourceCodeHash": "0x21e03ab7a5f518a21258669c82506b1d4d1141f8fd4f30bb385f9730580ddd3c" }, { "contractName": "Keccak256", "bytecodePath": "zkout/Keccak256.yul/contracts-preprocessed/precompiles/Keccak256.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/Keccak256.yul", - "bytecodeHash": "0x0100000f16ef9261284d26f08a560cd482ff7eb7944fe37ac99113aa4eb75188", + "bytecodeHash": "0x0100000fb95dd6f46682ea2f0b187124613531b459091a6c38dc9d0260e5fff1", "sourceCodeHash": "0xb454e7760732ce1fffc75174c8cf54dca422206cf1e52a29d274b310b574f26d" }, { "contractName": "P256Verify", "bytecodePath": "zkout/P256Verify.yul/contracts-preprocessed/precompiles/P256Verify.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/P256Verify.yul", - "bytecodeHash": "0x0100000ff914846f07b729f21be741f039c13d9c8e7c53e4db3a4c9a9f7e022d", + "bytecodeHash": "0x0100000f72c45ba0985fe38394a29445cb337c127afb0da5e94211d518a00949", "sourceCodeHash": "0x976b68d0362307313fd1aaea309eaa2d849187f37da451618c70dd3a6ac3cf3c" }, { "contractName": "SHA256", "bytecodePath": "zkout/SHA256.yul/contracts-preprocessed/precompiles/SHA256.yul.json", "sourceCodePath": "contracts-preprocessed/precompiles/SHA256.yul", - "bytecodeHash": "0x01000017cac2faad1aa8a1fd865fa464fbf092dbd8031dedb52fa6b8632e5b97", + "bytecodeHash": "0x010000176a7caf23abe1829a27684e6172e72e3b8a1d201364c5bbe53615202b", "sourceCodeHash": "0xfd4290467e26e992f39db9ca132e78ce99ce042b0254a368f1d7832dc94ddefb" }, { "contractName": "bootloader_test", "bytecodePath": "zkout/bootloader_test.yul/contracts-preprocessed/bootloader/bootloader_test.yul.json", "sourceCodePath": "bootloader/build/bootloader_test.yul", - "bytecodeHash": "0x010003ade02adac2c039832861a6649c6cbb7abbb2ff8542c6aefff7bde06a9c", + "bytecodeHash": "0x010003ad66a3c11e49c10fa3b03809e965e1983372bf5425e61182ac7a55d2e1", "sourceCodeHash": "0x006fdf461899dec5fdb34301c23e6819eb93e275907cbfc67d73fccfb47cae68" }, { "contractName": "dummy", "bytecodePath": "zkout/dummy.yul/contracts-preprocessed/bootloader/dummy.yul.json", "sourceCodePath": "bootloader/build/dummy.yul", - "bytecodeHash": "0x01000007b6aafb589f3b3d53466cb263cb237e75169fba7ba728aba0134007f9", + "bytecodeHash": "0x0100000799df180103cb4323acaa77800d219c3e00d3eeed7774d1fbdad4b930", "sourceCodeHash": "0xfac5ca11a9882425af93fe5bac6d10055b119cf13af79e6a2f4e74e8411b9c85" }, { "contractName": "fee_estimate", "bytecodePath": "zkout/fee_estimate.yul/contracts-preprocessed/bootloader/fee_estimate.yul.json", "sourceCodePath": "bootloader/build/fee_estimate.yul", - "bytecodeHash": "0x01000905327a3aeb212816e7e0f6c16c5acc491c714c06d823c4bbc7075b62d6", + "bytecodeHash": "0x01000905f08fe63941a99ae6f9da44c44d038cbc48a39d517bd24e672c5b50b7", "sourceCodeHash": "0x8a858319bac2924a3dee778218a7fe5e23898db0d87b02d7b783f94c5a02d257" }, { "contractName": "gas_test", "bytecodePath": "zkout/gas_test.yul/contracts-preprocessed/bootloader/gas_test.yul.json", "sourceCodePath": "bootloader/build/gas_test.yul", - "bytecodeHash": "0x01000871cdb46e23c5b65176cd772e368d255c80290058b89e9644efbe8d7c53", + "bytecodeHash": "0x01000871ca053253e09ee8d138c1fa7194bd3ef64b9ea36514aa13f997626d49", "sourceCodeHash": "0x89f5ad470f10e755fa57b82507518e571c24409a328bc33aeba26e9518ad1c3e" }, { "contractName": "playground_batch", "bytecodePath": "zkout/playground_batch.yul/contracts-preprocessed/bootloader/playground_batch.yul.json", "sourceCodePath": "bootloader/build/playground_batch.yul", - "bytecodeHash": "0x01000909408f87054598e7a1e9fbc58e0e9733b0ab5030618eef36ef746cac68", + "bytecodeHash": "0x01000909e749e13a2298999bd6a24030c144156b18f8531b9e4fdb009f23287a", "sourceCodeHash": "0x769448c4fd2b65c43d758ca5f34dd29d9b9dd3000fd0ec89cffcaf8d365a64fd" }, { "contractName": "proved_batch", "bytecodePath": "zkout/proved_batch.yul/contracts-preprocessed/bootloader/proved_batch.yul.json", "sourceCodePath": "bootloader/build/proved_batch.yul", - "bytecodeHash": "0x01000881f046342b70470a7e81423b5903dfe06669d01292e7dc6f8eb73bf404", + "bytecodeHash": "0x01000881ede3f4dc1d05626f241363b01670a395d54b74227348ed824f1c3dbd", "sourceCodeHash": "0x908bc6ddb34ef89b125e9637239a1149deacacd91255781d82a65a542a39036e" }, { "contractName": "transfer_test", "bytecodePath": "zkout/transfer_test.yul/contracts-preprocessed/bootloader/transfer_test.yul.json", "sourceCodePath": "bootloader/build/transfer_test.yul", - "bytecodeHash": "0x0100001532ccf5b061252699f6d2c677d987c775f48152271d5be4f02e41e454", + "bytecodeHash": "0x01000015904f1cc3ac2c66713ca1eaf00c27988a8d00515a743fb81a9919bdcc", "sourceCodeHash": "0xb828600c6f7366971580b68da39c3e449b9a0f922f52dd9841f33ae7f51ee71c" } ] diff --git a/system-contracts/foundry.toml b/system-contracts/foundry.toml index 4f5780943..98d9b22bd 100644 --- a/system-contracts/foundry.toml +++ b/system-contracts/foundry.toml @@ -10,6 +10,6 @@ remappings = [ ] [profile.default.zksync] -zksolc = "1.5.6" +zksolc = "1.5.7" enable_eravm_extensions = true suppressed_errors = ["sendtransfer"] diff --git a/system-contracts/hardhat.config.ts b/system-contracts/hardhat.config.ts index 5a6ab2986..a6e5dc44a 100644 --- a/system-contracts/hardhat.config.ts +++ b/system-contracts/hardhat.config.ts @@ -5,27 +5,11 @@ import "@matterlabs/hardhat-zksync-verify"; import "@nomiclabs/hardhat-ethers"; import "hardhat-typechain"; -// This version of system contracts requires a pre release of the compiler -const COMPILER_VERSION = "v1.5.6"; -const PRE_RELEASE_VERSION = "1.5.6"; -function getZksolcUrl(): string { - // @ts-ignore - const platform = { darwin: "macosx", linux: "linux", win32: "windows" }[process.platform]; - // @ts-ignore - const toolchain = { linux: "-musl", win32: "-gnu", darwin: "" }[process.platform]; - const arch = process.arch === "x64" ? "amd64" : process.arch; - const ext = process.platform === "win32" ? ".exe" : ""; - - return `https://github.com/matter-labs/era-compiler-solidity/releases/download/${PRE_RELEASE_VERSION}/zksolc-${platform}-${arch}${toolchain}-${COMPILER_VERSION}${ext}`; -} - -console.log(`Using zksolc from ${getZksolcUrl()}`); - export default { zksolc: { + version: "1.5.7", compilerSource: "binary", settings: { - compilerPath: getZksolcUrl(), enableEraVMExtensions: true, suppressedErrors: ["sendtransfer"], }, diff --git a/system-contracts/scripts/compile-yul.ts b/system-contracts/scripts/compile-yul.ts index e22f26b97..fd5061a5e 100644 --- a/system-contracts/scripts/compile-yul.ts +++ b/system-contracts/scripts/compile-yul.ts @@ -5,8 +5,8 @@ import * as fs from "fs"; import { Command } from "commander"; import * as _path from "path"; -const COMPILER_VERSION = "1.5.6"; -const IS_COMPILER_PRE_RELEASE = true; +const COMPILER_VERSION = "1.5.7"; +const IS_COMPILER_PRE_RELEASE = false; const CONTRACTS_DIR = "contracts-preprocessed"; const BOOTLOADER_DIR = "bootloader"; const TIMESTAMP_FILE_YUL = "last_compilation_yul.timestamp"; diff --git a/system-contracts/scripts/compile-zasm.ts b/system-contracts/scripts/compile-zasm.ts index 8ae15bf16..de0f84d4c 100644 --- a/system-contracts/scripts/compile-zasm.ts +++ b/system-contracts/scripts/compile-zasm.ts @@ -3,8 +3,8 @@ import type { CompilerPaths } from "./utils"; import { spawn, compilerLocation, prepareCompilerPaths } from "./utils"; import * as fs from "fs"; -const COMPILER_VERSION = "1.5.6"; -const IS_COMPILER_PRE_RELEASE = true; +const COMPILER_VERSION = "1.5.7"; +const IS_COMPILER_PRE_RELEASE = false; export async function compileZasm(paths: CompilerPaths, file: string) { const zksolcLocation = await compilerLocation(COMPILER_VERSION, IS_COMPILER_PRE_RELEASE); From a4c8e641d2601fbc59f45810a1da618cdfce6966 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 29 Nov 2024 17:43:25 +0100 Subject: [PATCH 143/183] feat(EVM): Cleanup in system contracts (#1103) --- .../l2-deps/ISystemContext.sol | 2 - system-contracts/SystemContractsHashes.json | 56 ++++++------ system-contracts/bootloader/bootloader.yul | 8 +- .../contracts/BootloaderUtilities.sol | 22 +++-- system-contracts/contracts/Constants.sol | 2 + .../contracts/ContractDeployer.sol | 87 +++++++++++-------- system-contracts/contracts/DefaultAccount.sol | 25 +++--- .../contracts/abstract/SystemContractBase.sol | 2 +- .../interfaces/IContractDeployer.sol | 1 + .../libraries/SystemContractHelper.sol | 3 +- .../contracts/libraries/TransactionHelper.sol | 23 +++-- .../contracts/libraries/Utils.sol | 29 +++++-- .../test/AccountCodeStorage.spec.ts | 30 +++++++ .../test/KnownCodesStorage.spec.ts | 32 +++++++ 14 files changed, 212 insertions(+), 110 deletions(-) diff --git a/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.sol b/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.sol index ea224aa3f..cdc1140e7 100644 --- a/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.sol +++ b/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.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.21; -import {AllowedBytecodeTypes} from "./AllowedBytecodeTypes.sol"; - interface ISystemContext { /// @notice Set the chain configuration. /// @param _newChainId The chainId diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index bab27441c..f4ff24991 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,50 +3,50 @@ "contractName": "AccountCodeStorage", "bytecodePath": "zkout/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x0100007780de9dddbd3da02c056b91ad5d01021c0272d1dd27e38c85be45f3d4", + "bytecodeHash": "0x01000073b3bc1272f774b6d9be05721f6d7eb8d092fdea1b98a6cfaebc31d140", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "zkout/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f11cb97db853fb46dd01e679db89935588782b80c3084c427d093b5a18", - "sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19" + "bytecodeHash": "0x010006f3cf25451770a2adca96ba19aa526caccc63ea71cb175969ff2fd48546", + "sourceCodeHash": "0x10f30ac1a7098c7fddec2659ac43422783e8d3fdde02a3ba4d3ff45d451d7001" }, { "contractName": "ComplexUpgrader", "bytecodePath": "zkout/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x010000479ec3174e7edbf5369412199c3ff17a48e77e607f226fdcf67207843a", + "bytecodeHash": "0x010000472e443f07ce828b486959956abf538f1079bf6a48d576d8a586638550", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "zkout/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013fd2cd1bd37fc9ed112a69359d30dc9c40882c87de1b7af64d62613914", + "bytecodeHash": "0x0100013fdefa9989778db1a64e851f672c664591ca30cdf5da346ad6096cae57", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "zkout/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010006719baa3a0e4e111366d448c79adb46ff2f998e043568d7b95117bd5619", - "sourceCodeHash": "0x3a03e66288c63fb72abe909ae829fa9495dce051753687d4395d41971847826b" + "bytecodeHash": "0x010006716d699486ec8c5575a116f09c7173e6a1287a23f56dc7a03b695fc7d6", + "sourceCodeHash": "0x5df9078b16d7cfc294017aa1db6a81893853753fc9f767d91c543ec29b7b7555" }, { "contractName": "Create2Factory", "bytecodePath": "zkout/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003fc288d0f1eafca23362a2ea07e786ff71ae01c543100bbf4784b8fe54", + "bytecodeHash": "0x0100003f1e72af6311dafd0cfdf6d8b06458657fa0e01504129e8402730a94b0", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "zkout/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x01000509e7947a94bd0bb3c7269859bb7b2f289b47cdd989ed5acbf860521f01", - "sourceCodeHash": "0xef448fac6b6f1c217b6495ee134a3553e02dfb920fd46bc71de33672e64d9ab8" + "bytecodeHash": "0x0100050bd43ebd46a1816b43b3e95929855823ccf22649d3fb3ea20429f873a5", + "sourceCodeHash": "0x92339614c273a2ede1d5933c8af2443505f12971862c13fe343470c3b001f9a8" }, { "contractName": "EmptyContract", @@ -59,56 +59,56 @@ "contractName": "ImmutableSimulator", "bytecodePath": "zkout/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x01000033e14187c8f85799a7bd6d59193352b707e5794bd70b17e8afcae4172e", + "bytecodeHash": "0x010000336a67d5bcf7e6eaaa518fedb0081b3cd8576df3827bc3e2c52c507ecd", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "zkout/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cd1538f9a3418025676a99c9ce36b4e6e70ad823bd600e36882d5dc188", + "bytecodeHash": "0x010000cde2ac89fde1127da56da7be365205e6728bc6c158e8298809dc4b4de2", "sourceCodeHash": "0x851fb5e170dfde39f1f9bc74654ec0b8f8f1d4c2fb20c06c77844c1e3ee0659a" }, { "contractName": "L1Messenger", "bytecodePath": "zkout/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x0100026558794f82978b3d29a3327ccab77f742e9f79e36ffc93e66994fc39ca", + "bytecodeHash": "0x01000263945edeb299d65573cfe866f0e0be60d9b4a8e2a95f51fa9ac5a53cd2", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "zkout/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000db4abe83a75377dbf217a1c8d6d9fc26908765ffb47fbfab4aa92cf69f", + "bytecodeHash": "0x010000db88ef9018d889e667652a27f5d2658aec6886a784a13259e7338c7ca1", "sourceCodeHash": "0xdea518b1ea16718b0f0ec6155b227a8bc8f51374a9eebf7bc17cfe84433df740" }, { "contractName": "MsgValueSimulator", "bytecodePath": "zkout/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x01000059c4299cd7ab15bf9351db6ae362d28665c5cf2674b655ee54415ec8fe", + "bytecodeHash": "0x0100005905d49dbc9a0d6cf2b20ab7a91d78ae90d27405f4345b0514cd677e15", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "zkout/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cfbdc4f0313c148014f051e2ab25f989ee1c8257457954d5343125261a", + "bytecodeHash": "0x010000cfc02c13988766e9866f1ab4a3ac8a193e57ac8912e6fd1161948b9d1d", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "zkout/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041a54610aa9ac7259adbe837383ed1d1aefd7cfb0446413f679e0b8767", + "bytecodeHash": "0x0100004175cbb16026df5b85b84655b4fb084bb04231a105baebcc8260e5d851", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "zkout/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c516d2f256a0394133c07f8b5793d791f363ffd989fb90be614ca78411", + "bytecodeHash": "0x010001c58b2d426f41453b876e4c860d931b5442ce46c998bd53e2721507ae72", "sourceCodeHash": "0xe2f6eb015d260aafe9405b28ef3ec27921add4de7f329b7ef61e0aa6c9365e29" }, { @@ -199,8 +199,8 @@ "contractName": "bootloader_test", "bytecodePath": "zkout/bootloader_test.yul/contracts-preprocessed/bootloader/bootloader_test.yul.json", "sourceCodePath": "bootloader/build/bootloader_test.yul", - "bytecodeHash": "0x010003ad063d9ac388d3d8bd3739eb77d74589a0b2b50abb279203200f8a293a", - "sourceCodeHash": "0x4cac84261775ca327cf22d8b7595e020d03415e7c13311a8601b81543da1d94d" + "bytecodeHash": "0x010003ad66485b2f2802f2028e7da75e226fae47b815627f05ac541dd646a1dd", + "sourceCodeHash": "0xe4a10be4e60eccc1ec39dbf7b07c12a16f2202f1904eba045ea66d13adfe5659" }, { "contractName": "dummy", @@ -213,29 +213,29 @@ "contractName": "fee_estimate", "bytecodePath": "zkout/fee_estimate.yul/contracts-preprocessed/bootloader/fee_estimate.yul.json", "sourceCodePath": "bootloader/build/fee_estimate.yul", - "bytecodeHash": "0x010008fd2a790cf99a83a7fd8741851411b7c5d7bd016474d6f97416065803f2", - "sourceCodeHash": "0xaa1836b407eae63dcac7b99cfb91defdbac7baa6f4c049f9118181fff58c37ec" + "bytecodeHash": "0x010008fdfeb9d95c6ff3801b96a1a5ad3917132ac5abb0df4f5da81f5c565978", + "sourceCodeHash": "0xb1ae1f7bccf8f5d75dfe36c33322937bc2b3565a59ea23d8360caa8f9565f348" }, { "contractName": "gas_test", "bytecodePath": "zkout/gas_test.yul/contracts-preprocessed/bootloader/gas_test.yul.json", "sourceCodePath": "bootloader/build/gas_test.yul", - "bytecodeHash": "0x0100086961ed6952306ea7ccc5f6b4d06575714980e05d9d597d9f18306df17b", - "sourceCodeHash": "0x8c224e2e3c6e7c516ce5fbbbe841ecaaeb239e15e24ac0f2f7b4a8a11e9d9dfa" + "bytecodeHash": "0x010008693e2b453a622a5ec0ac8b79844750f21a3b7476786388d17b59c17f0f", + "sourceCodeHash": "0x8797a5687a30f46369f8248093537162c3ebc512fb89c0fe8662e2cbe4525ada" }, { "contractName": "playground_batch", "bytecodePath": "zkout/playground_batch.yul/contracts-preprocessed/bootloader/playground_batch.yul.json", "sourceCodePath": "bootloader/build/playground_batch.yul", - "bytecodeHash": "0x01000903a83cceb9cea9f84fd73f41cec5e689679311844e55d4689e725ae75c", - "sourceCodeHash": "0x04d534fd13610e0a82531f4d2a466e5b6caf814a50fb3a1b0f7d77918f078d26" + "bytecodeHash": "0x010009031e40639e1d7d6a38a16aa2777f26b37ad8a4dce4bcdbec9bbaf2dbf8", + "sourceCodeHash": "0x6babd6fcf22f0b28fcbcdf5f085a7fb354aacc5f95d7ab0b6fe36f24254a30ce" }, { "contractName": "proved_batch", "bytecodePath": "zkout/proved_batch.yul/contracts-preprocessed/bootloader/proved_batch.yul.json", "sourceCodePath": "bootloader/build/proved_batch.yul", - "bytecodeHash": "0x0100087b1be05b8e462c1dc50e99eead337f09d42f26be0b4c643da5ba269bc1", - "sourceCodeHash": "0x72564482cf4e0e31bd47dbd15729952dd6994508c06f5065c2106920ad8e5a33" + "bytecodeHash": "0x0100087b7bb1d234655ca6c31e3ba8cb383c13f9738b1de7e5e2b39b34648677", + "sourceCodeHash": "0x9b17825ead64bf51912bc549ea9981e2b91301f0c937defe8202fe2f5678ce63" }, { "contractName": "transfer_test", diff --git a/system-contracts/bootloader/bootloader.yul b/system-contracts/bootloader/bootloader.yul index a42f9c4ee..429532b6d 100644 --- a/system-contracts/bootloader/bootloader.yul +++ b/system-contracts/bootloader/bootloader.yul @@ -3126,7 +3126,7 @@ object "Bootloader" { assertEq(gt(getFrom(innerTxDataOffset), MAX_SYSTEM_CONTRACT_ADDR()), 1, "from in kernel space") - // assertEq(getReserved1(innerTxDataOffset), 0, "reserved1 non zero") + // reserved1 used as marker that tx doesn't have field "to" assertEq(getReserved2(innerTxDataOffset), 0, "reserved2 non zero") assertEq(getReserved3(innerTxDataOffset), 0, "reserved3 non zero") assertEq(getFactoryDepsBytesLength(innerTxDataOffset), 0, "factory deps non zero") @@ -3152,7 +3152,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") + // reserved1 used as marker that tx doesn't have field "to" assertEq(getReserved2(innerTxDataOffset), 0, "reserved2 non zero") assertEq(getReserved3(innerTxDataOffset), 0, "reserved3 non zero") assertEq(getFactoryDepsBytesLength(innerTxDataOffset), 0, "factory deps non zero") @@ -3175,7 +3175,7 @@ object "Bootloader" { assertEq(getReserved0(innerTxDataOffset), 0, "reserved0 non zero") - //assertEq(getReserved1(innerTxDataOffset), 0, "reserved1 non zero") + // reserved1 used as marker that tx doesn't have field "to" assertEq(getReserved2(innerTxDataOffset), 0, "reserved2 non zero") assertEq(getReserved3(innerTxDataOffset), 0, "reserved3 non zero") assertEq(getFactoryDepsBytesLength(innerTxDataOffset), 0, "factory deps non zero") @@ -3194,7 +3194,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") + // reserved1 used as marker that tx doesn't have field "to" assertEq(getReserved2(innerTxDataOffset), 0, "reserved2 non zero") assertEq(getReserved3(innerTxDataOffset), 0, "reserved3 non zero") } diff --git a/system-contracts/contracts/BootloaderUtilities.sol b/system-contracts/contracts/BootloaderUtilities.sol index 94c6663a4..554a79aba 100644 --- a/system-contracts/contracts/BootloaderUtilities.sol +++ b/system-contracts/contracts/BootloaderUtilities.sol @@ -59,9 +59,11 @@ contract BootloaderUtilities is IBootloaderUtilities { encodedGasParam = bytes.concat(encodedGasPrice, encodedGasLimit); } - bytes memory encodedTo = _transaction.reserved[1] == 0 - ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) - : bytes(hex"80"); + // "to" field is empty if it is EVM deploy tx + bytes memory encodedTo = _transaction.reserved[1] == 1 + ? bytes(hex"80") + : RLPEncoder.encodeAddress(address(uint160(_transaction.to))); + 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. @@ -150,9 +152,10 @@ 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 = _transaction.reserved[1] == 0 - ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) - : bytes(hex"80"); + // "to" field is empty if it is EVM deploy tx + bytes memory encodedTo = _transaction.reserved[1] == 1 + ? bytes(hex"80") + : RLPEncoder.encodeAddress(address(uint160(_transaction.to))); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // solhint-disable-next-line func-named-parameters encodedFixedLengthParams = bytes.concat( @@ -250,9 +253,10 @@ 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 = _transaction.reserved[1] == 0 - ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) - : bytes(hex"80"); + // "to" field is empty if it is EVM deploy tx + bytes memory encodedTo = _transaction.reserved[1] == 1 + ? bytes(hex"80") + : RLPEncoder.encodeAddress(address(uint160(_transaction.to))); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // solhint-disable-next-line func-named-parameters encodedFixedLengthParams = bytes.concat( diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index 545529721..36309b111 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -164,5 +164,7 @@ uint256 constant BLOB_SIZE_BYTES = 126_976; /// @dev Max number of blobs currently supported uint256 constant MAX_NUMBER_OF_BLOBS = 6; +/// @dev Marker of EraVM bytecode uint8 constant ERA_VM_BYTECODE_FLAG = 1; +/// @dev Marker of EVM bytecode uint8 constant EVM_BYTECODE_FLAG = 2; \ No newline at end of file diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index bb0b5b5d6..16b9d65bc 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -22,13 +22,16 @@ import {Unauthorized, InvalidAllowedBytecodeTypesMode, InvalidNonceOrderingChang * do not need to be published anymore. */ contract ContractDeployer is IContractDeployer, SystemContractBase { + /// @dev Prefix for EVM contracts hashes storage slots. + uint256 private constant EVM_HASHES_PREFIX = 1 << 254; + /// @dev keccak256("ALLOWED_BYTECODE_TYPES_MODE_SLOT"). + bytes32 private constant ALLOWED_BYTECODE_TYPES_MODE_SLOT = + 0xd70708d0b933e26eab552567ce3a8ad69e6fbec9a2a68f16d51bd417a47d9d3b; + /// @notice Information about an account contract. /// @dev For EOA and simple contracts (i.e. not accounts) this value is 0. mapping(address => AccountInfo) internal accountInfo; - uint256 private constant EVM_HASHES_PREFIX = 1 << 254; - uint256 private constant ALLOWED_BYTECODE_TYPES_MODE_SLOT = 2; - modifier onlySelf() { if (msg.sender != address(this)) { revert Unauthorized(msg.sender); @@ -36,15 +39,16 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _; } - function evmCodeHash(address _address) external view returns (bytes32 _hash) { - _hash = _getEvmCodeHash(_address); - } - - /// @notice Returns what types of bytecode are allowed to be deployed on this chain + /// @notice Returns what types of bytecode are allowed to be deployed on this chain. function allowedBytecodeTypesToDeploy() external view returns (AllowedBytecodeTypes mode) { mode = _getAllowedBytecodeTypesMode(); } + /// @notice Returns keccak of EVM bytecode at address if it is an EVM contract. Returns bytes32(0) if it isn't a EVM contract. + 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]; @@ -169,6 +173,9 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { return createAccount(_salt, _bytecodeHash, _input, AccountAbstractionVersion.None); } + /// @notice Deploys an EVM contract using address derivation of EVM's `CREATE` opcode. + /// @param _initCode The init code for the contract. + /// Note: this method may be callable only in system mode. function createEVM(bytes calldata _initCode) external payable override onlySystemCall returns (address) { uint256 senderNonce; // If the account is an EOA, use the min nonce. If it's a contract, use deployment nonce @@ -177,15 +184,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.getMinNonce(msg.sender) - 1; } else { // Deploy from EraVM context - - // #### Uncomment for Solidity semantic tests (EraVM contracts are deployed with 0 nonce, but tests expect 1) - /* - senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.getDeploymentNonce(msg.sender); - if (senderNonce == 0) { - NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); - } - */ - senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); } @@ -196,10 +194,10 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { 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 + /// @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. function create2EVM( bytes32 _salt, bytes calldata _initCode @@ -214,9 +212,13 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { return newAddress; } + /// @notice Method used by EVM emulator to check if contract can be deployed. + /// @param _salt The CREATE2 salt. + /// @param _evmBytecodeHash The keccak of EVM code to be deployed (initCode). + /// Note: this method may be callable only by the EVM emulator. function precreateEvmAccountFromEmulator( bytes32 _salt, - bytes32 evmBytecodeHash + bytes32 _evmBytecodeHash ) public onlySystemCallFromEvmEmulator returns (address newAddress) { if (_getAllowedBytecodeTypesMode() != AllowedBytecodeTypes.EraVmAndEVM) { revert EVMEmulationNotSupported(); @@ -224,9 +226,9 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { uint256 senderNonce = NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); - if (evmBytecodeHash != bytes32(0)) { + if (_evmBytecodeHash != bytes32(0)) { // Create2 case - newAddress = Utils.getNewAddressCreate2EVM(msg.sender, _salt, evmBytecodeHash); + newAddress = Utils.getNewAddressCreate2EVM(msg.sender, _salt, _evmBytecodeHash); } else { // Create case newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); @@ -234,19 +236,25 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { // Unfortunately we can not provide revert reason as it would break EVM compatibility // we should not increase nonce in case of collision + // solhint-disable-next-line reason-string, gas-custom-errors require(NONCE_HOLDER_SYSTEM_CONTRACT.getRawNonce(newAddress) == 0x0); + // solhint-disable-next-line reason-string, gas-custom-errors require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.getCodeHash(uint256(uint160(newAddress))) == 0x0); return newAddress; } - /// Note: only possible revert case should be due to revert in the called constructor + /// @notice Method used by EVM emulator to deploy contracts. + /// @param _newAddress The address of the contract to be deployed. + /// @param _initCode The EVM code to be deployed (initCode). + /// Note: only possible revert case should be due to revert in the called constructor. + /// Note: this method may be callable only by the EVM emulator. function createEvmFromEmulator( - address newAddress, + address _newAddress, bytes calldata _initCode ) external payable onlySystemCallFromEvmEmulator returns (uint256, address) { - uint256 constructorReturnEvmGas = _evmDeployOnAddress(msg.sender, newAddress, _initCode); - return (constructorReturnEvmGas, newAddress); + uint256 constructorReturnEvmGas = _evmDeployOnAddress(msg.sender, _newAddress, _initCode); + return (constructorReturnEvmGas, _newAddress); } /// @notice Deploys a contract account with similar address derivation rules to the EVM's `CREATE2` opcode. @@ -403,6 +411,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { revert NonEmptyAccount(); } + // solhint-disable-next-line func-named-parameters _performDeployOnAddress(_bytecodeHash, _newAddress, _aaVersion, _input, true); } @@ -416,7 +425,9 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { } // Unfortunately we can not provide revert reason as it would break EVM compatibility + // solhint-disable-next-line reason-string, gas-custom-errors require(NONCE_HOLDER_SYSTEM_CONTRACT.getRawNonce(_newAddress) == 0x0); + // solhint-disable-next-line reason-string, gas-custom-errors require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.getCodeHash(uint256(uint160(_newAddress))) == 0x0); return _performDeployOnAddressEVM(_sender, _newAddress, AccountAbstractionVersion.None, _initCode); } @@ -451,8 +462,8 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { }); } - /// @notice Deploy a certain bytecode on the address. - /// @param _sender The deployer address + /// @notice Deploy a certain EVM bytecode on the address. + /// @param _sender The deployer 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. @@ -544,6 +555,11 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { emit ContractDeployed(_sender, _bytecodeHash, _newAddress); } + /// @notice Transfers the `msg.value` ETH to the deployed account & invokes its constructor. + /// This function must revert in case the deployment fails. + /// @param _sender The msg.sender to be used in the constructor. + /// @param _newAddress The address of the deployed contract. + /// @param _input The constructor calldata. function _constructEVMContract( address _sender, address _newAddress, @@ -558,7 +574,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { // 2. Set the constructed code hash on the account _storeConstructingByteCodeHashOnAddress( _newAddress, - // Dummy EVM bytecode hash just to call simulator. + // Dummy EVM bytecode hash just to call emulator. // The second byte is `0x01` to indicate that it is being constructed. bytes32(0x0201000000000000000000000000000000000000000000000000000000000000) ); @@ -578,10 +594,11 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _isSystem: false }); + // Returned data bytes have structure: bytecode.constructorReturnEvmGas assembly { let dataLen := mload(paddedBytecode) constructorReturnEvmGas := mload(add(paddedBytecode, dataLen)) - mstore(paddedBytecode, sub(dataLen, 0x20)) + mstore(paddedBytecode, sub(dataLen, 0x20)) // shrink paddedBytecode } bytes32 versionedCodeHash = KNOWN_CODE_STORAGE_CONTRACT.publishEVMBytecode(paddedBytecode); @@ -600,15 +617,13 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { function _setEvmCodeHash(address _address, bytes32 _hash) internal { assembly { - let slot := or(EVM_HASHES_PREFIX, _address) - sstore(slot, _hash) + sstore(or(EVM_HASHES_PREFIX, _address), _hash) } } function _getEvmCodeHash(address _address) internal view returns (bytes32 _hash) { assembly { - let slot := or(EVM_HASHES_PREFIX, _address) - _hash := sload(slot) + _hash := sload(or(EVM_HASHES_PREFIX, _address)) } } diff --git a/system-contracts/contracts/DefaultAccount.sol b/system-contracts/contracts/DefaultAccount.sol index c42d6dbbd..cb479f538 100644 --- a/system-contracts/contracts/DefaultAccount.sol +++ b/system-contracts/contracts/DefaultAccount.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {IAccount, ACCOUNT_VALIDATION_SUCCESS_MAGIC} from "./interfaces/IAccount.sol"; -import {TransactionHelper, Transaction} from "./libraries/TransactionHelper.sol"; +import {TransactionHelper, Transaction, L1_TO_L2_TX_TYPE} from "./libraries/TransactionHelper.sol"; import {SystemContractsCaller} from "./libraries/SystemContractsCaller.sol"; import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; @@ -139,15 +139,20 @@ contract DefaultAccount is IAccount { bytes calldata data = _transaction.data; uint32 gas = Utils.safeCastToU32(gasleft()); - if ((_transaction.reserved[1] != 0) && (to == address(0))) { - // Note, that createEVM can only be called with "isSystem" flag. - SystemContractsCaller.systemCallWithPropagatedRevert( - uint32(gasleft()), - address(DEPLOYER_SYSTEM_CONTRACT), - value, - abi.encodeCall(DEPLOYER_SYSTEM_CONTRACT.createEVM, (data)) - ); - return; + if (to == address(0)) { + // for L1 to L2 txs we use reserved[2], for other types reserved[1] + bool isEvmDeployTx = _transaction.reserved[_transaction.txType == L1_TO_L2_TX_TYPE ? 2 : 1] == 1; + + if (isEvmDeployTx) { + // Note, that createEVM can only be called with "isSystem" flag. + SystemContractsCaller.systemCallWithPropagatedRevert( + uint32(gasleft()), + address(DEPLOYER_SYSTEM_CONTRACT), + value, + abi.encodeCall(DEPLOYER_SYSTEM_CONTRACT.createEVM, (data)) + ); + return; + } } // Note, that the deployment method from the deployer contract can only be called with a "systemCall" flag. diff --git a/system-contracts/contracts/abstract/SystemContractBase.sol b/system-contracts/contracts/abstract/SystemContractBase.sol index 613f7d49c..abc5b8006 100644 --- a/system-contracts/contracts/abstract/SystemContractBase.sol +++ b/system-contracts/contracts/abstract/SystemContractBase.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; import {SystemContractHelper} from "../libraries/SystemContractHelper.sol"; -import {BOOTLOADER_FORMAL_ADDRESS, FORCE_DEPLOYER, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} from "../Constants.sol"; +import {BOOTLOADER_FORMAL_ADDRESS, FORCE_DEPLOYER} from "../Constants.sol"; import {SystemCallFlagRequired, Unauthorized, CallerMustBeSystemContract, CallerMustBeBootloader, CallerMustBeForceDeployer, CallerMustBeEvmContract} from "../SystemContractErrors.sol"; /** diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index ef94427a8..93ce7bd46 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -106,6 +106,7 @@ interface IContractDeployer { function create2EVM(bytes32 _salt, bytes calldata _initCode) external payable returns (address); + /// @notice Returns keccak of EVM bytecode at address if it is an EVM contract. Returns bytes32(0) if it isn't a EVM contract. function evmCodeHash(address) external view returns (bytes32); /// @notice Changes what types of bytecodes are allowed to be deployed on the chain. Can be used only during upgrades. diff --git a/system-contracts/contracts/libraries/SystemContractHelper.sol b/system-contracts/contracts/libraries/SystemContractHelper.sol index 6b3690149..e76d25057 100644 --- a/system-contracts/contracts/libraries/SystemContractHelper.sol +++ b/system-contracts/contracts/libraries/SystemContractHelper.sol @@ -3,9 +3,8 @@ pragma solidity ^0.8.20; import {MAX_SYSTEM_CONTRACT_ADDRESS, ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT} 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} from "./SystemContractsCaller.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 {IndexOutOfBounds, FailedToChargeGas} from "../SystemContractErrors.sol"; uint256 constant UINT32_MASK = type(uint32).max; diff --git a/system-contracts/contracts/libraries/TransactionHelper.sol b/system-contracts/contracts/libraries/TransactionHelper.sol index 10f3a10fc..9eccfd93e 100644 --- a/system-contracts/contracts/libraries/TransactionHelper.sol +++ b/system-contracts/contracts/libraries/TransactionHelper.sol @@ -20,6 +20,8 @@ uint8 constant LEGACY_TX_TYPE = 0x0; uint8 constant EIP_2930_TX_TYPE = 0x01; /// @dev The type id of EIP1559 transactions. uint8 constant EIP_1559_TX_TYPE = 0x02; +/// @dev The type id of L1 to L2 transactions. +uint8 constant L1_TO_L2_TX_TYPE = 0xFF; /// @notice Structure used to represent a ZKsync transaction. struct Transaction { @@ -163,9 +165,10 @@ library TransactionHelper { encodedGasParam = bytes.concat(encodedGasPrice, encodedGasLimit); } - bytes memory encodedTo = _transaction.reserved[1] == 0 - ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) - : bytes(hex"80"); + // "to" field is empty if it is EVM deploy tx + bytes memory encodedTo = _transaction.reserved[1] == 1 + ? bytes(hex"80") + : RLPEncoder.encodeAddress(address(uint160(_transaction.to))); 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. @@ -234,9 +237,10 @@ 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 = _transaction.reserved[1] == 0 - ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) - : bytes(hex"80"); + // "to" field is empty if it is EVM deploy tx + bytes memory encodedTo = _transaction.reserved[1] == 1 + ? bytes(hex"80") + : RLPEncoder.encodeAddress(address(uint160(_transaction.to))); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // solhint-disable-next-line func-named-parameters encodedFixedLengthParams = bytes.concat( @@ -309,9 +313,10 @@ 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 = _transaction.reserved[1] == 0 - ? RLPEncoder.encodeAddress(address(uint160(_transaction.to))) - : bytes(hex"80"); + // "to" field is empty if it is EVM deploy tx + bytes memory encodedTo = _transaction.reserved[1] == 1 + ? bytes(hex"80") + : RLPEncoder.encodeAddress(address(uint160(_transaction.to))); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // solhint-disable-next-line func-named-parameters encodedFixedLengthParams = bytes.concat( diff --git a/system-contracts/contracts/libraries/Utils.sol b/system-contracts/contracts/libraries/Utils.sol index 211a23d83..bc423c885 100644 --- a/system-contracts/contracts/libraries/Utils.sol +++ b/system-contracts/contracts/libraries/Utils.sol @@ -45,25 +45,36 @@ library Utils { return uint24(_x); } + /// @return If this bytecode hash for EVM contract or not function isCodeHashEVM(bytes32 _bytecodeHash) internal pure returns (bool) { return (uint8(_bytecodeHash[0]) == EVM_BYTECODE_FLAG); } - /// @return codeLength The bytecode length in bytes - function bytecodeLenInBytes(bytes32 _bytecodeHash) internal pure returns (uint256 codeLength) { - if (uint8(_bytecodeHash[0]) == ERA_VM_BYTECODE_FLAG) { - codeLength = bytecodeLenInWords(_bytecodeHash) << 5; // _bytecodeHash * 32 - } else if (uint8(_bytecodeHash[0]) == EVM_BYTECODE_FLAG) { - codeLength = bytecodeLenInWords(_bytecodeHash); - } else { - codeLength = 0; + /// @return codeLengthInBytes The bytecode length in bytes + function bytecodeLenInBytes(bytes32 _bytecodeHash) internal pure returns (uint256 codeLengthInBytes) { + unchecked { + uint256 decodedCodeLength = uint256(uint8(_bytecodeHash[2])) * 256 + uint256(uint8(_bytecodeHash[3])); + if (isCodeHashEVM(_bytecodeHash)) { + // length is encoded in bytes + codeLengthInBytes = decodedCodeLength; + } else { + // length is encoded in words + codeLengthInBytes = decodedCodeLength << 5; // * 32 + } } } /// @return codeLengthInWords The bytecode length in machine words function bytecodeLenInWords(bytes32 _bytecodeHash) internal pure returns (uint256 codeLengthInWords) { unchecked { - codeLengthInWords = uint256(uint8(_bytecodeHash[2])) * 256 + uint256(uint8(_bytecodeHash[3])); + uint256 decodedCodeLength = uint256(uint8(_bytecodeHash[2])) * 256 + uint256(uint8(_bytecodeHash[3])); + if (isCodeHashEVM(_bytecodeHash)) { + // length is encoded in bytes + codeLengthInWords = (decodedCodeLength + 31) / 32; // rounded up + } else { + // length is encoded in words + codeLengthInWords = decodedCodeLength; + } } } diff --git a/system-contracts/test/AccountCodeStorage.spec.ts b/system-contracts/test/AccountCodeStorage.spec.ts index dca782e01..f1b44a051 100644 --- a/system-contracts/test/AccountCodeStorage.spec.ts +++ b/system-contracts/test/AccountCodeStorage.spec.ts @@ -11,6 +11,7 @@ import { } from "./shared/constants"; import { prepareEnvironment, setResult } from "./shared/mocks"; import { deployContractOnAddress, getWallets } from "./shared/utils"; +import { ZERO_HASH } from "zksync-ethers/build/utils"; describe("AccountCodeStorage tests", function () { let wallet: Wallet; @@ -20,6 +21,7 @@ describe("AccountCodeStorage tests", function () { const CONSTRUCTING_BYTECODE_HASH = "0x0101FFFFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"; const CONSTRUCTED_BYTECODE_HASH = "0x0100FFFFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"; + const CONSTRUCTED_EVM_BYTECODE_HASH = "0x0200FFFFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"; const RANDOM_ADDRESS = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; before(async () => { @@ -143,6 +145,22 @@ describe("AccountCodeStorage tests", function () { }); }); + describe("isAccountEVM", function () { + it("false", async () => { + expect(await accountCodeStorage.isAccountEVM(RANDOM_ADDRESS)).to.be.eq(false); + }); + + it("true", async () => { + await accountCodeStorage + .connect(deployerAccount) + .storeAccountConstructedCodeHash(RANDOM_ADDRESS, CONSTRUCTED_EVM_BYTECODE_HASH); + + expect(await accountCodeStorage.isAccountEVM(RANDOM_ADDRESS)).to.be.eq(true); + + await unsetCodeHash(accountCodeStorage, RANDOM_ADDRESS); + }); + }); + describe("getCodeHash", function () { it("precompile min address", async () => { // Check that the smallest precompile has EMPTY_STRING_KECCAK hash @@ -186,6 +204,18 @@ describe("AccountCodeStorage tests", function () { await unsetCodeHash(accountCodeStorage, RANDOM_ADDRESS); }); + it("constructed EVM contract", async () => { + await deployContractOnAddress(TEST_DEPLOYER_SYSTEM_CONTRACT_ADDRESS, "ContractDeployer", false); + + await accountCodeStorage + .connect(deployerAccount) + .storeAccountConstructedCodeHash(RANDOM_ADDRESS, CONSTRUCTED_EVM_BYTECODE_HASH); + + expect(await accountCodeStorage.getCodeHash(RANDOM_ADDRESS)).to.be.eq(ZERO_HASH); // contract deployer doesn't have this contract hash + + await unsetCodeHash(accountCodeStorage, RANDOM_ADDRESS); + }); + it("zero", async () => { await setResult("NonceHolder", "getRawNonce", [RANDOM_ADDRESS], { failure: false, diff --git a/system-contracts/test/KnownCodesStorage.spec.ts b/system-contracts/test/KnownCodesStorage.spec.ts index 36a034cb7..395249eec 100644 --- a/system-contracts/test/KnownCodesStorage.spec.ts +++ b/system-contracts/test/KnownCodesStorage.spec.ts @@ -6,6 +6,7 @@ import { KnownCodesStorageFactory } from "../typechain"; import { TEST_BOOTLOADER_FORMAL_ADDRESS, TEST_COMPRESSOR_CONTRACT_ADDRESS, + TEST_DEPLOYER_SYSTEM_CONTRACT_ADDRESS, TEST_KNOWN_CODE_STORAGE_CONTRACT_ADDRESS, } from "./shared/constants"; import { encodeCalldata, getMock, prepareEnvironment } from "./shared/mocks"; @@ -84,6 +85,37 @@ describe("KnownCodesStorage tests", function () { }); }); + describe("publishEVMBytecode", function () { + let deployerAccount: ethers.Signer; + + const InvalidBytecode = + "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + beforeEach(async () => { + deployerAccount = await ethers.getImpersonatedSigner(TEST_DEPLOYER_SYSTEM_CONTRACT_ADDRESS); + }); + + it("non-deployer failed to call", async () => { + await expect(knownCodesStorage.publishEVMBytecode("0x00")).to.be.revertedWithCustomError( + knownCodesStorage, + "Unauthorized" + ); + }); + + it("bytecode with even length failed to publish", async () => { + await expect( + knownCodesStorage.connect(deployerAccount).publishEVMBytecode(InvalidBytecode) + ).to.be.revertedWithCustomError(knownCodesStorage, "MalformedBytecode"); + }); + + it("invalid length bytecode failed to call", async () => { + await expect(knownCodesStorage.connect(deployerAccount).publishEVMBytecode("0x00")).to.be.revertedWithCustomError( + knownCodesStorage, + "MalformedBytecode" + ); + }); + }); + describe("markFactoryDeps", function () { it("non-bootloader failed to call", async () => { await expect( From 7e242cf0a7e56b59cc17e5121fc88bd7316548ea Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 2 Dec 2024 09:32:07 +0100 Subject: [PATCH 144/183] fix(EVM): Change deploy flow for EIP712 transactions (#1106) --- system-contracts/SystemContractsHashes.json | 4 ++-- system-contracts/contracts/DefaultAccount.sol | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index f4ff24991..0461d525a 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -45,8 +45,8 @@ "contractName": "DefaultAccount", "bytecodePath": "zkout/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100050bd43ebd46a1816b43b3e95929855823ccf22649d3fb3ea20429f873a5", - "sourceCodeHash": "0x92339614c273a2ede1d5933c8af2443505f12971862c13fe343470c3b001f9a8" + "bytecodeHash": "0x0100050d33f6a197513ccb0df249162508e8be5c92bd2d15b5980d859dd489d9", + "sourceCodeHash": "0x63ee6c1d26248c235bc970e5c288f005281cc81d0300aea28e43360f53d0cf1d" }, { "contractName": "EmptyContract", diff --git a/system-contracts/contracts/DefaultAccount.sol b/system-contracts/contracts/DefaultAccount.sol index cb479f538..499a22d2e 100644 --- a/system-contracts/contracts/DefaultAccount.sol +++ b/system-contracts/contracts/DefaultAccount.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {IAccount, ACCOUNT_VALIDATION_SUCCESS_MAGIC} from "./interfaces/IAccount.sol"; -import {TransactionHelper, Transaction, L1_TO_L2_TX_TYPE} from "./libraries/TransactionHelper.sol"; +import {TransactionHelper, Transaction, EIP_712_TX_TYPE, L1_TO_L2_TX_TYPE} from "./libraries/TransactionHelper.sol"; import {SystemContractsCaller} from "./libraries/SystemContractsCaller.sol"; import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; @@ -140,13 +140,19 @@ contract DefaultAccount is IAccount { uint32 gas = Utils.safeCastToU32(gasleft()); if (to == address(0)) { - // for L1 to L2 txs we use reserved[2], for other types reserved[1] - bool isEvmDeployTx = _transaction.reserved[_transaction.txType == L1_TO_L2_TX_TYPE ? 2 : 1] == 1; + bool isEvmDeployTx; + if (_transaction.txType == EIP_712_TX_TYPE) { + // With EIP712 type user can't sign empty "to" field. So we consider tx to 0x00 with data as deploy + isEvmDeployTx = _transaction.data.length != 0; + } else { + // For L1 to L2 txs we use reserved[2], for other types reserved[1] + isEvmDeployTx = _transaction.reserved[_transaction.txType == L1_TO_L2_TX_TYPE ? 2 : 1] == 1; + } if (isEvmDeployTx) { // Note, that createEVM can only be called with "isSystem" flag. SystemContractsCaller.systemCallWithPropagatedRevert( - uint32(gasleft()), + gas, address(DEPLOYER_SYSTEM_CONTRACT), value, abi.encodeCall(DEPLOYER_SYSTEM_CONTRACT.createEVM, (data)) From 0c00649a442d12932c7848b22741acd0ccceb5b8 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 6 Dec 2024 21:40:00 +0100 Subject: [PATCH 145/183] feat(EVM): Remove reserved field usage for EVM deploy using custom txs (#1129) --- system-contracts/SystemContractsHashes.json | 4 +-- system-contracts/contracts/DefaultAccount.sol | 29 +++++++------------ 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 0461d525a..5968185fb 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -45,8 +45,8 @@ "contractName": "DefaultAccount", "bytecodePath": "zkout/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100050d33f6a197513ccb0df249162508e8be5c92bd2d15b5980d859dd489d9", - "sourceCodeHash": "0x63ee6c1d26248c235bc970e5c288f005281cc81d0300aea28e43360f53d0cf1d" + "bytecodeHash": "0x0100050b78c8bba8aa0816a1b754d8cd6647d84de85a00db0bf4fbb603524e51", + "sourceCodeHash": "0x300c864fcb3bc6a562875c7b1d83df15d466515da0a878a426b1aaeac26f3656" }, { "contractName": "EmptyContract", diff --git a/system-contracts/contracts/DefaultAccount.sol b/system-contracts/contracts/DefaultAccount.sol index 499a22d2e..58731d929 100644 --- a/system-contracts/contracts/DefaultAccount.sol +++ b/system-contracts/contracts/DefaultAccount.sol @@ -140,24 +140,17 @@ contract DefaultAccount is IAccount { uint32 gas = Utils.safeCastToU32(gasleft()); if (to == address(0)) { - bool isEvmDeployTx; - if (_transaction.txType == EIP_712_TX_TYPE) { - // With EIP712 type user can't sign empty "to" field. So we consider tx to 0x00 with data as deploy - isEvmDeployTx = _transaction.data.length != 0; - } else { - // For L1 to L2 txs we use reserved[2], for other types reserved[1] - isEvmDeployTx = _transaction.reserved[_transaction.txType == L1_TO_L2_TX_TYPE ? 2 : 1] == 1; - } - - if (isEvmDeployTx) { - // Note, that createEVM can only be called with "isSystem" flag. - SystemContractsCaller.systemCallWithPropagatedRevert( - gas, - address(DEPLOYER_SYSTEM_CONTRACT), - value, - abi.encodeCall(DEPLOYER_SYSTEM_CONTRACT.createEVM, (data)) - ); - return; + if (_transaction.txType != EIP_712_TX_TYPE && _transaction.txType != L1_TO_L2_TX_TYPE) { + if (_transaction.reserved[1] == 1) { + // Note, that createEVM can only be called with "isSystem" flag. + SystemContractsCaller.systemCallWithPropagatedRevert( + gas, + address(DEPLOYER_SYSTEM_CONTRACT), + value, + abi.encodeCall(DEPLOYER_SYSTEM_CONTRACT.createEVM, (data)) + ); + return; + } } } From 5ec848642671b737b0bafae0336039e97ad99f91 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 6 Dec 2024 21:56:11 +0100 Subject: [PATCH 146/183] feat(EVM): Return evm gas used in external create methods (#1130) --- system-contracts/SystemContractsHashes.json | 32 +++++++++---------- .../contracts/ContractDeployer.sol | 16 ++++++---- .../interfaces/IContractDeployer.sol | 7 ++-- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index 5968185fb..f8c17571a 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,49 +3,49 @@ "contractName": "AccountCodeStorage", "bytecodePath": "zkout/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x01000073b3bc1272f774b6d9be05721f6d7eb8d092fdea1b98a6cfaebc31d140", + "bytecodeHash": "0x0100007317994a1fc65998cd916c99f52951e58cefedce3c330aacf7fd20dd94", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "zkout/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f3cf25451770a2adca96ba19aa526caccc63ea71cb175969ff2fd48546", + "bytecodeHash": "0x010006f3eaa43c2aeece380d750965b772ae2d8874f942fe598445977118fd23", "sourceCodeHash": "0x10f30ac1a7098c7fddec2659ac43422783e8d3fdde02a3ba4d3ff45d451d7001" }, { "contractName": "ComplexUpgrader", "bytecodePath": "zkout/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x010000472e443f07ce828b486959956abf538f1079bf6a48d576d8a586638550", + "bytecodeHash": "0x010000470769b6a1ab43e898daf381c7df9753c51e8001e06b6daa39357f42a8", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "zkout/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013fdefa9989778db1a64e851f672c664591ca30cdf5da346ad6096cae57", + "bytecodeHash": "0x0100013f2c94736cbc8e992f7e84df5e01a64d15bf2443c2dda5bee7476c9575", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "zkout/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x010006716d699486ec8c5575a116f09c7173e6a1287a23f56dc7a03b695fc7d6", - "sourceCodeHash": "0x5df9078b16d7cfc294017aa1db6a81893853753fc9f767d91c543ec29b7b7555" + "bytecodeHash": "0x01000673f8b088c2c27ab36f025b222a908368fd22b461bf97b12784753b2fea", + "sourceCodeHash": "0xbb9a2717e6fd1da15df4ef1862d2e55e661547f973478bb1fc3cab1ea3cca575" }, { "contractName": "Create2Factory", "bytecodePath": "zkout/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003f1e72af6311dafd0cfdf6d8b06458657fa0e01504129e8402730a94b0", + "bytecodeHash": "0x0100003ff00c4656ed039bac6da4b2f56c01acf662faff586f7032d33de48634", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "zkout/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100050b78c8bba8aa0816a1b754d8cd6647d84de85a00db0bf4fbb603524e51", + "bytecodeHash": "0x0100050bcb0eb0f55ec0821967b509b2ae60fa52ff94f0f934b4de464e2f3a5d", "sourceCodeHash": "0x300c864fcb3bc6a562875c7b1d83df15d466515da0a878a426b1aaeac26f3656" }, { @@ -59,56 +59,56 @@ "contractName": "ImmutableSimulator", "bytecodePath": "zkout/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x010000336a67d5bcf7e6eaaa518fedb0081b3cd8576df3827bc3e2c52c507ecd", + "bytecodeHash": "0x010000338218e48deb166b7e6486e558038239530c8f30bdbc0b15dffc671aa6", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "zkout/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cde2ac89fde1127da56da7be365205e6728bc6c158e8298809dc4b4de2", + "bytecodeHash": "0x010000cd7ef93ae3e09683ca91c705700694f3f9bd25f5d0d5fecd38d667eccf", "sourceCodeHash": "0x851fb5e170dfde39f1f9bc74654ec0b8f8f1d4c2fb20c06c77844c1e3ee0659a" }, { "contractName": "L1Messenger", "bytecodePath": "zkout/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000263945edeb299d65573cfe866f0e0be60d9b4a8e2a95f51fa9ac5a53cd2", + "bytecodeHash": "0x01000263345d82f95b6533501ee84340770418287866931d64899423815527f8", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "zkout/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000db88ef9018d889e667652a27f5d2658aec6886a784a13259e7338c7ca1", + "bytecodeHash": "0x010000dbc44fbd6fd01e930a4cbbb59a17b285bd86fc5dbe11f59d1f375f6286", "sourceCodeHash": "0xdea518b1ea16718b0f0ec6155b227a8bc8f51374a9eebf7bc17cfe84433df740" }, { "contractName": "MsgValueSimulator", "bytecodePath": "zkout/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x0100005905d49dbc9a0d6cf2b20ab7a91d78ae90d27405f4345b0514cd677e15", + "bytecodeHash": "0x010000594d78e2e2a0f0fa224c8ba6b3fd8ab8b283bff7420c1b565fe8a61ee7", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "zkout/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cfc02c13988766e9866f1ab4a3ac8a193e57ac8912e6fd1161948b9d1d", + "bytecodeHash": "0x010000cf17e28b461edeaf764b45bd824cf6b1a653478624bfa361c813a61b5d", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "zkout/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x0100004175cbb16026df5b85b84655b4fb084bb04231a105baebcc8260e5d851", + "bytecodeHash": "0x01000041dab57304eb3d41b96948d580eb388f303bdf058c15b71afcef0ffac0", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "zkout/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c58b2d426f41453b876e4c860d931b5442ce46c998bd53e2721507ae72", + "bytecodeHash": "0x010001c54c88a8fb2427458c7b4caddc0c7927e396a60a5e690408d36a25eceb", "sourceCodeHash": "0xe2f6eb015d260aafe9405b28ef3ec27921add4de7f329b7ef61e0aa6c9365e29" }, { diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 16b9d65bc..7032bacad 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -176,7 +176,9 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { /// @notice Deploys an EVM contract using address derivation of EVM's `CREATE` opcode. /// @param _initCode The init code for the contract. /// Note: this method may be callable only in system mode. - function createEVM(bytes calldata _initCode) external payable override onlySystemCall returns (address) { + /// @return The amount of EVM gas used. + /// @return The address of created contract. + function createEVM(bytes calldata _initCode) external payable override onlySystemCall returns (uint256, address) { uint256 senderNonce; // If the account is an EOA, use the min nonce. If it's a contract, use deployment nonce if (msg.sender == tx.origin) { @@ -189,27 +191,29 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); - _evmDeployOnAddress(msg.sender, newAddress, _initCode); + uint256 evmGasUsed = _evmDeployOnAddress(msg.sender, newAddress, _initCode); - return newAddress; + return (evmGasUsed, 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. + /// @return The amount of EVM gas used. + /// @return The address of created contract. function create2EVM( bytes32 _salt, bytes calldata _initCode - ) external payable override onlySystemCall returns (address) { + ) external payable override onlySystemCall returns (uint256, address) { NONCE_HOLDER_SYSTEM_CONTRACT.incrementDeploymentNonce(msg.sender); // 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(msg.sender, newAddress, _initCode); + uint256 evmGasUsed = _evmDeployOnAddress(msg.sender, newAddress, _initCode); - return newAddress; + return (evmGasUsed, newAddress); } /// @notice Method used by EVM emulator to check if contract can be deployed. diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index 93ce7bd46..83bf2392e 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -102,9 +102,12 @@ 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 createEVM(bytes calldata _initCode) external payable returns (uint256 evmGasUsed, address newAddress); - function create2EVM(bytes32 _salt, bytes calldata _initCode) external payable returns (address); + function create2EVM( + bytes32 _salt, + bytes calldata _initCode + ) external payable returns (uint256 evmGasUsed, address newAddress); /// @notice Returns keccak of EVM bytecode at address if it is an EVM contract. Returns bytes32(0) if it isn't a EVM contract. function evmCodeHash(address) external view returns (bytes32); From 77983ce5e15d5a9839dbd79dc556e472961b8f5e Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 6 Dec 2024 22:23:20 +0100 Subject: [PATCH 147/183] chore(EVM): Merge V25 release branch (#1132) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Danil Co-authored-by: Danil Co-authored-by: Vlad Bochok <41153528+vladbochok@users.noreply.github.com> Co-authored-by: Grzegorz Prusak Co-authored-by: koloz193 Co-authored-by: Bence Haromi <56651250+benceharomi@users.noreply.github.com> Co-authored-by: Moshe Shababo <17073733+moshababo@users.noreply.github.com> Co-authored-by: Akosh Farkash Co-authored-by: Bruno França Co-authored-by: Roman Brodetski Co-authored-by: vladbochok Co-authored-by: Stanislav Bezkorovainyi Co-authored-by: otani Co-authored-by: Ivan Schasny Co-authored-by: Ivan Schasny <31857042+ischasny@users.noreply.github.com> --- yarn.lock | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/yarn.lock b/yarn.lock index 4df7c8718..47e9a6aab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8023,3 +8023,10 @@ zksync-ethers@^5.9.0: integrity sha512-Y2Mx6ovvxO6UdC2dePLguVzvNToOY8iLWeq5ne+jgGSJxAi/f4He/NF6FNsf6x1aWX0o8dy4Df8RcOQXAkj5qw== dependencies: ethers "~5.7.0" + +zksync-web3@^0.15.4: + version "0.15.5" + resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.15.5.tgz#aabe379464963ab573e15948660a709f409b5316" + integrity sha512-97gB7OKJL4spegl8fGO54g6cvTd/75G6yFWZWEa2J09zhjTrfqabbwE/GwiUJkFQ5BbzoH4JaTlVz1hoYZI+DQ== + dependencies: + ethers "~5.7.0" From 93888b5ec969cb7c09a01596887876df9918c18b Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 10 Dec 2024 13:30:32 +0100 Subject: [PATCH 148/183] fix(EVM): Fix dev merge artifact (#1138) --- l1-contracts/deploy-scripts/DeployL1.s.sol | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index 3dd7da0b0..cdbaff661 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -303,17 +303,10 @@ contract DeployL1Script is Script { } function deployChainAdmin() internal { - bytes memory accessControlRestrictionBytecode = abi.encodePacked( + bytes memory bytecode = abi.encodePacked( type(ChainAdmin).creationCode, - abi.encode(uint256(0), config.ownerAddress) + abi.encode(config.ownerAddress, address(0)) ); - - address accessControlRestriction = deployViaCreate2(accessControlRestrictionBytecode); - console.log("Access control restriction deployed at:", accessControlRestriction); - address[] memory restrictions = new address[](1); - restrictions[0] = accessControlRestriction; - - bytes memory bytecode = abi.encodePacked(type(ChainAdmin).creationCode, abi.encode(restrictions)); address contractAddress = deployViaCreate2(bytecode); console.log("ChainAdmin deployed at:", contractAddress); addresses.chainAdmin = contractAddress; From 933e1d5a139156a8fd9ba23143823a589355f93e Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 10 Dec 2024 16:33:06 +0100 Subject: [PATCH 149/183] fix(EVM): Fx l1 foundry deploy scripts (#1139) --- l1-contracts/deploy-scripts/RegisterHyperchain.s.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol index c622d28c0..7dfa127d2 100644 --- a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol +++ b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol @@ -161,9 +161,10 @@ contract RegisterHyperchainScript is Script { ? AllowedBytecodeTypes.EraVmAndEVM : AllowedBytecodeTypes.EraVm; - bytes memory diamondCutEncoded = abi.encode(config.diamondCutData); + bytes memory initData = abi.encode(config.diamondCutData, allowedBytecodeTypesMode); vm.recordLogs(); + bytes memory data = abi.encodeCall( bridgehub.createNewChain, ( @@ -172,7 +173,7 @@ contract RegisterHyperchainScript is Script { config.baseToken, config.bridgehubCreateNewChainSalt, msg.sender, - abi.encode(diamondCutEncoded, allowedBytecodeTypesMode) + initData ) ); From ed6f4d1f8fcde854e084cd1d237fd80698f2da19 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 10 Dec 2024 17:23:03 +0100 Subject: [PATCH 150/183] fix(EVM) Fix config parsing in L1 foundry deploy script (#1140) --- l1-contracts/deploy-scripts/DeployL1.s.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/l1-contracts/deploy-scripts/DeployL1.s.sol b/l1-contracts/deploy-scripts/DeployL1.s.sol index cdbaff661..085bebfac 100644 --- a/l1-contracts/deploy-scripts/DeployL1.s.sol +++ b/l1-contracts/deploy-scripts/DeployL1.s.sol @@ -215,6 +215,7 @@ contract DeployL1Script is Script { config.contracts.diamondInitMinimalL2GasPrice = toml.readUint("$.contracts.diamond_init_minimal_l2_gas_price"); config.contracts.defaultAAHash = toml.readBytes32("$.contracts.default_aa_hash"); config.contracts.bootloaderHash = toml.readBytes32("$.contracts.bootloader_hash"); + config.contracts.evmEmulatorHash = toml.readBytes32("$.contracts.evm_emulator_hash"); config.tokens.tokenWethAddress = toml.readAddress("$.tokens.token_weth_address"); } From 44bd426a0b5915da962519119185ded8c0277eee Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 27 Nov 2024 17:17:17 +0100 Subject: [PATCH 151/183] fix(EVM): Add static MCOPY cost (#1081) --- system-contracts/contracts/EvmEmulator.yul | 4 ++++ system-contracts/evm-emulator/EvmEmulatorLoop.template.yul | 2 ++ 2 files changed, 6 insertions(+) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index f9a9c0d75..40d167ac5 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -2061,6 +2061,8 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0x5E { // OP_MCOPY + evmGasLeft := chargeGas(evmGasLeft, 3) + let destOffset, offset, size popStackCheck(sp, 3) destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) @@ -5109,6 +5111,8 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0x5E { // OP_MCOPY + evmGasLeft := chargeGas(evmGasLeft, 3) + let destOffset, offset, size popStackCheck(sp, 3) destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 78e1a5315..87dbf7e8c 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -836,6 +836,8 @@ for { } true { } { ip := add(ip, 1) } case 0x5E { // OP_MCOPY + evmGasLeft := chargeGas(evmGasLeft, 3) + let destOffset, offset, size popStackCheck(sp, 3) destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) From 8e8323de73e15d1c88a0b90d008a7c13528c4a29 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 27 Nov 2024 17:18:16 +0100 Subject: [PATCH 152/183] fix(EVM): Cleanup in checkMemIsAccessible (#1082) --- system-contracts/contracts/EvmEmulator.yul | 20 ++++++------------- .../EvmEmulatorFunctions.template.yul | 10 +++------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 40d167ac5..da253ce42 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -167,10 +167,6 @@ object "EvmEmulator" { max := 0x400000 // 4MB } - function MAX_MEMORY_SLOT() -> max { - max := add(MEM_OFFSET(), MAX_POSSIBLE_MEM_LEN()) - } - function MAX_UINT() -> max_uint { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } @@ -282,10 +278,10 @@ object "EvmEmulator" { } } - function checkMemIsAccessible(index, offset) { - checkOverflow(index, offset) + function checkMemIsAccessible(relativeOffset, size) { + checkOverflow(relativeOffset, size) - if gt(add(index, offset), MAX_MEMORY_SLOT()) { + if gt(add(relativeOffset, size), MAX_POSSIBLE_MEM_LEN()) { panic() } } @@ -3217,10 +3213,6 @@ object "EvmEmulator" { max := 0x400000 // 4MB } - function MAX_MEMORY_SLOT() -> max { - max := add(MEM_OFFSET(), MAX_POSSIBLE_MEM_LEN()) - } - function MAX_UINT() -> max_uint { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } @@ -3332,10 +3324,10 @@ object "EvmEmulator" { } } - function checkMemIsAccessible(index, offset) { - checkOverflow(index, offset) + function checkMemIsAccessible(relativeOffset, size) { + checkOverflow(relativeOffset, size) - if gt(add(index, offset), MAX_MEMORY_SLOT()) { + if gt(add(relativeOffset, size), MAX_POSSIBLE_MEM_LEN()) { panic() } } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 58736a58d..eb7e554af 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -105,10 +105,6 @@ function MAX_POSSIBLE_MEM_LEN() -> max { max := 0x400000 // 4MB } -function MAX_MEMORY_SLOT() -> max { - max := add(MEM_OFFSET(), MAX_POSSIBLE_MEM_LEN()) -} - function MAX_UINT() -> max_uint { max_uint := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff } @@ -220,10 +216,10 @@ function expandMemory2(retOffset, retSize, argsOffset, argsSize) -> maxExpand { } } -function checkMemIsAccessible(index, offset) { - checkOverflow(index, offset) +function checkMemIsAccessible(relativeOffset, size) { + checkOverflow(relativeOffset, size) - if gt(add(index, offset), MAX_MEMORY_SLOT()) { + if gt(add(relativeOffset, size), MAX_POSSIBLE_MEM_LEN()) { panic() } } From ef91e5233e31550fca911d59300c717b7525f565 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 27 Nov 2024 17:19:56 +0100 Subject: [PATCH 153/183] fix(EVM): Simplify OP_PC (#1084) --- system-contracts/contracts/EvmEmulator.yul | 12 ++++++------ .../evm-emulator/EvmEmulatorLoop.template.yul | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index da253ce42..303b7ffd5 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -2010,10 +2010,10 @@ object "EvmEmulator" { } case 0x58 { // OP_PC evmGasLeft := chargeGas(evmGasLeft, 2) - ip := add(ip, 1) - // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_LEN_OFFSET()), 33), stackHead) + sp, stackHead := pushStackItem(sp, sub(ip, BYTECODE_OFFSET()), stackHead) + + ip := add(ip, 1) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft, 2) @@ -5056,10 +5056,10 @@ object "EvmEmulator" { } case 0x58 { // OP_PC evmGasLeft := chargeGas(evmGasLeft, 2) - ip := add(ip, 1) - // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_LEN_OFFSET()), 33), stackHead) + sp, stackHead := pushStackItem(sp, sub(ip, BYTECODE_OFFSET()), stackHead) + + ip := add(ip, 1) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft, 2) diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 87dbf7e8c..20897c518 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -789,10 +789,10 @@ for { } true { } { } case 0x58 { // OP_PC evmGasLeft := chargeGas(evmGasLeft, 2) - ip := add(ip, 1) - // PC = ip - 32 (bytecode size) - 1 (current instruction) - sp, stackHead := pushStackItem(sp, sub(sub(ip, BYTECODE_LEN_OFFSET()), 33), stackHead) + sp, stackHead := pushStackItem(sp, sub(ip, BYTECODE_OFFSET()), stackHead) + + ip := add(ip, 1) } case 0x59 { // OP_MSIZE evmGasLeft := chargeGas(evmGasLeft, 2) From b649f5f5cc0cba54479688d31e98d585542391d0 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 27 Nov 2024 17:25:48 +0100 Subject: [PATCH 154/183] fix(EVM): Do not charge additionally for EraVM decommit (#1086) --- system-contracts/contracts/EvmEmulator.yul | 46 ------------------- .../EvmEmulatorFunctions.template.yul | 23 ---------- 2 files changed, 69 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 303b7ffd5..e4d7e98b5 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -185,9 +185,6 @@ object "EvmEmulator" { 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 //////////////////////////////////////////////////////////////// @@ -848,17 +845,6 @@ object "EvmEmulator" { // Call native ZkVm contract from EVM context function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas - let decommitZkVmGasCost := decommitmentCost(addr) - - // we are going to charge decommit cost even if address is already warm - // decommit cost is subtracted from the callee frame - switch gt(decommitZkVmGasCost, zkEvmGasToPass) - case 0 { - zkEvmGasToPass := sub(zkEvmGasToPass, decommitZkVmGasCost) - } - default { - zkEvmGasToPass := 0 - } if gt(zkEvmGasToPass, UINT32_MAX()) { // just in case zkEvmGasToPass := UINT32_MAX() @@ -886,15 +872,6 @@ object "EvmEmulator" { } } - function decommitmentCost(addr) -> cost { - // charge for contract decommitment - let byteSize := extcodesize(addr) - cost := mul( - div(add(byteSize, 31), 32), // rounding up - DECOMMIT_COST_PER_WORD() - ) - } - function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 gasToPass := oldGasToPass @@ -3231,9 +3208,6 @@ object "EvmEmulator" { 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 //////////////////////////////////////////////////////////////// @@ -3894,17 +3868,6 @@ object "EvmEmulator" { // Call native ZkVm contract from EVM context function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas - let decommitZkVmGasCost := decommitmentCost(addr) - - // we are going to charge decommit cost even if address is already warm - // decommit cost is subtracted from the callee frame - switch gt(decommitZkVmGasCost, zkEvmGasToPass) - case 0 { - zkEvmGasToPass := sub(zkEvmGasToPass, decommitZkVmGasCost) - } - default { - zkEvmGasToPass := 0 - } if gt(zkEvmGasToPass, UINT32_MAX()) { // just in case zkEvmGasToPass := UINT32_MAX() @@ -3932,15 +3895,6 @@ object "EvmEmulator" { } } - function decommitmentCost(addr) -> cost { - // charge for contract decommitment - let byteSize := extcodesize(addr) - cost := mul( - div(add(byteSize, 31), 32), // rounding up - DECOMMIT_COST_PER_WORD() - ) - } - function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 gasToPass := oldGasToPass diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index eb7e554af..96d0df147 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -123,9 +123,6 @@ function MSG_VALUE_SIMULATOR_STIPEND_GAS() -> gas_stipend { 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 //////////////////////////////////////////////////////////////// @@ -786,17 +783,6 @@ function callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, args // Call native ZkVm contract from EVM context function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas - let decommitZkVmGasCost := decommitmentCost(addr) - - // we are going to charge decommit cost even if address is already warm - // decommit cost is subtracted from the callee frame - switch gt(decommitZkVmGasCost, zkEvmGasToPass) - case 0 { - zkEvmGasToPass := sub(zkEvmGasToPass, decommitZkVmGasCost) - } - default { - zkEvmGasToPass := 0 - } if gt(zkEvmGasToPass, UINT32_MAX()) { // just in case zkEvmGasToPass := UINT32_MAX() @@ -824,15 +810,6 @@ function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffs } } -function decommitmentCost(addr) -> cost { - // charge for contract decommitment - let byteSize := extcodesize(addr) - cost := mul( - div(add(byteSize, 31), 32), // rounding up - DECOMMIT_COST_PER_WORD() - ) -} - function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { let maxGasToPass := sub(evmGasLeft, shr(6, evmGasLeft)) // evmGasLeft >> 6 == evmGasLeft/64 gasToPass := oldGasToPass From 5db2a306c2e8fbbb104fe09881e585ce5439d61b Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 27 Nov 2024 17:31:58 +0100 Subject: [PATCH 155/183] fix(EVM): Fix stack overflow check (#1085) --- system-contracts/contracts/EvmEmulator.yul | 28 ++++++++----------- .../EvmEmulatorFunctions.template.yul | 14 ++++------ 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index e4d7e98b5..cf7cfd1a9 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -132,8 +132,12 @@ object "EvmEmulator" { offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } + function MAX_STACK_SLOT_OFFSET() -> offset { + offset := add(STACK_OFFSET(), mul(1023, 32)) + } + function BYTECODE_LEN_OFFSET() -> offset { - offset := add(STACK_OFFSET(), mul(1024, 32)) + offset := add(MAX_STACK_SLOT_OFFSET(), 32) } function BYTECODE_OFFSET() -> offset { @@ -507,7 +511,7 @@ object "EvmEmulator" { } function pushStackItem(sp, item, oldStackHead) -> newSp, stackHead { - if iszero(lt(sp, BYTECODE_LEN_OFFSET())) { + if iszero(lt(sp, MAX_STACK_SLOT_OFFSET())) { panic() } @@ -534,12 +538,6 @@ object "EvmEmulator" { } } - function pushStackCheck(sp, numInputs) { - if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_LEN_OFFSET())) { - panic() - } - } - function accessStackHead(sp, stackHead) -> value { if lt(sp, STACK_OFFSET()) { panic() @@ -3155,8 +3153,12 @@ object "EvmEmulator" { offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } + function MAX_STACK_SLOT_OFFSET() -> offset { + offset := add(STACK_OFFSET(), mul(1023, 32)) + } + function BYTECODE_LEN_OFFSET() -> offset { - offset := add(STACK_OFFSET(), mul(1024, 32)) + offset := add(MAX_STACK_SLOT_OFFSET(), 32) } function BYTECODE_OFFSET() -> offset { @@ -3530,7 +3532,7 @@ object "EvmEmulator" { } function pushStackItem(sp, item, oldStackHead) -> newSp, stackHead { - if iszero(lt(sp, BYTECODE_LEN_OFFSET())) { + if iszero(lt(sp, MAX_STACK_SLOT_OFFSET())) { panic() } @@ -3557,12 +3559,6 @@ object "EvmEmulator" { } } - function pushStackCheck(sp, numInputs) { - if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_LEN_OFFSET())) { - panic() - } - } - function accessStackHead(sp, stackHead) -> value { if lt(sp, STACK_OFFSET()) { panic() diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 96d0df147..e58879762 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -70,8 +70,12 @@ function STACK_OFFSET() -> offset { offset := add(LAST_RETURNDATA_SIZE_OFFSET(), 64) } +function MAX_STACK_SLOT_OFFSET() -> offset { + offset := add(STACK_OFFSET(), mul(1023, 32)) +} + function BYTECODE_LEN_OFFSET() -> offset { - offset := add(STACK_OFFSET(), mul(1024, 32)) + offset := add(MAX_STACK_SLOT_OFFSET(), 32) } function BYTECODE_OFFSET() -> offset { @@ -445,7 +449,7 @@ function popStackItem(sp, oldStackHead) -> a, newSp, stackHead { } function pushStackItem(sp, item, oldStackHead) -> newSp, stackHead { - if iszero(lt(sp, BYTECODE_LEN_OFFSET())) { + if iszero(lt(sp, MAX_STACK_SLOT_OFFSET())) { panic() } @@ -472,12 +476,6 @@ function popStackCheck(sp, numInputs) { } } -function pushStackCheck(sp, numInputs) { - if iszero(lt(add(sp, mul(0x20, sub(numInputs, 1))), BYTECODE_LEN_OFFSET())) { - panic() - } -} - function accessStackHead(sp, stackHead) -> value { if lt(sp, STACK_OFFSET()) { panic() From ba50e1931cdafb29c0f9d817eb9445399cd5d12a Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 27 Nov 2024 17:33:14 +0100 Subject: [PATCH 156/183] fix(EVM): Add stack overflow check in dup (#1087) --- system-contracts/contracts/EvmEmulator.yul | 10 ++++++++++ .../evm-emulator/EvmEmulatorFunctions.template.yul | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index cf7cfd1a9..86169cfbb 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -476,6 +476,11 @@ object "EvmEmulator" { function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) + + if iszero(lt(sp, MAX_STACK_SLOT_OFFSET())) { + panic() + } + let tempSp := sub(sp, mul(0x20, sub(position, 1))) if lt(tempSp, STACK_OFFSET()) { @@ -3497,6 +3502,11 @@ object "EvmEmulator" { function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) + + if iszero(lt(sp, MAX_STACK_SLOT_OFFSET())) { + panic() + } + let tempSp := sub(sp, mul(0x20, sub(position, 1))) if lt(tempSp, STACK_OFFSET()) { diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index e58879762..bf71a04e7 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -414,6 +414,11 @@ function performSystemCallRevertable(to, dataLength) -> success { function dupStackItem(sp, evmGas, position, oldStackHead) -> newSp, evmGasLeft, stackHead { evmGasLeft := chargeGas(evmGas, 3) + + if iszero(lt(sp, MAX_STACK_SLOT_OFFSET())) { + panic() + } + let tempSp := sub(sp, mul(0x20, sub(position, 1))) if lt(tempSp, STACK_OFFSET()) { From 30d56adc805e9844e5987eea905b75da2804fa3a Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 27 Nov 2024 17:37:22 +0100 Subject: [PATCH 157/183] fix(EVM): Fix SSTORE warmth check (#1089) --- system-contracts/contracts/EvmEmulator.yul | 2 ++ system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul | 1 + 2 files changed, 3 insertions(+) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 86169cfbb..6de4661d6 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -593,6 +593,7 @@ object "EvmEmulator" { performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) + originalValue := currentValue if returndatasize() { isWarm := true returndatacopy(0, 0, 32) @@ -3619,6 +3620,7 @@ object "EvmEmulator" { performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) + originalValue := currentValue if returndatasize() { isWarm := true returndatacopy(0, 0, 32) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index bf71a04e7..2fffe58c1 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -531,6 +531,7 @@ function warmSlot(key, currentValue) -> isWarm, originalValue { performSystemCall(EVM_GAS_MANAGER_CONTRACT(), 65) + originalValue := currentValue if returndatasize() { isWarm := true returndatacopy(0, 0, 32) From 6fe12575d598cc8e0f0b701a9319890759c6ef9d Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 27 Nov 2024 17:46:19 +0100 Subject: [PATCH 158/183] fix(EVM): Fix CALL in static context (#1091) --- system-contracts/contracts/EvmEmulator.yul | 32 ++++++++----------- .../EvmEmulatorFunctions.template.yul | 8 +++-- .../evm-emulator/EvmEmulatorLoop.template.yul | 8 +---- 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 6de4661d6..fea544e05 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -641,7 +641,7 @@ object "EvmEmulator" { // CALLS FUNCTIONALITY //////////////////////////////////////////////////////////////// - function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { + function performCall(oldSp, evmGasLeft, oldStackHead, isStatic) -> newGasLeft, sp, stackHead { let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 7) @@ -673,6 +673,10 @@ object "EvmEmulator" { gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) if gt(value, 0) { + if isStatic { + panic() + } + gasUsed := add(gasUsed, 9000) // positive_value_cost if isAddrEmpty(addr) { @@ -696,7 +700,7 @@ object "EvmEmulator" { argsSize, add(retOffset, MEM_OFFSET()), retSize, - false + isStatic ) newGasLeft := add(evmGasLeft, frameGasLeft) @@ -2627,13 +2631,7 @@ object "EvmEmulator" { } case 0xF1 { // OP_CALL // A function was implemented in order to avoid stack depth errors. - switch isStatic - case 0 { - evmGasLeft, sp, stackHead := performCall(sp, evmGasLeft, stackHead) - } - default { - evmGasLeft, sp, stackHead := performStaticCall(sp, evmGasLeft, stackHead) - } + evmGasLeft, sp, stackHead := performCall(sp, evmGasLeft, stackHead, isStatic) ip := add(ip, 1) } case 0xF3 { // OP_RETURN @@ -3668,7 +3666,7 @@ object "EvmEmulator" { // CALLS FUNCTIONALITY //////////////////////////////////////////////////////////////// - function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { + function performCall(oldSp, evmGasLeft, oldStackHead, isStatic) -> newGasLeft, sp, stackHead { let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 7) @@ -3700,6 +3698,10 @@ object "EvmEmulator" { gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) if gt(value, 0) { + if isStatic { + panic() + } + gasUsed := add(gasUsed, 9000) // positive_value_cost if isAddrEmpty(addr) { @@ -3723,7 +3725,7 @@ object "EvmEmulator" { argsSize, add(retOffset, MEM_OFFSET()), retSize, - false + isStatic ) newGasLeft := add(evmGasLeft, frameGasLeft) @@ -5654,13 +5656,7 @@ object "EvmEmulator" { } case 0xF1 { // OP_CALL // A function was implemented in order to avoid stack depth errors. - switch isStatic - case 0 { - evmGasLeft, sp, stackHead := performCall(sp, evmGasLeft, stackHead) - } - default { - evmGasLeft, sp, stackHead := performStaticCall(sp, evmGasLeft, stackHead) - } + evmGasLeft, sp, stackHead := performCall(sp, evmGasLeft, stackHead, isStatic) ip := add(ip, 1) } case 0xF3 { // OP_RETURN diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 2fffe58c1..81b2d84ac 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -579,7 +579,7 @@ function resetEvmFrame() { // CALLS FUNCTIONALITY //////////////////////////////////////////////////////////////// -function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { +function performCall(oldSp, evmGasLeft, oldStackHead, isStatic) -> newGasLeft, sp, stackHead { let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 7) @@ -611,6 +611,10 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) if gt(value, 0) { + if isStatic { + panic() + } + gasUsed := add(gasUsed, 9000) // positive_value_cost if isAddrEmpty(addr) { @@ -634,7 +638,7 @@ function performCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHe argsSize, add(retOffset, MEM_OFFSET()), retSize, - false + isStatic ) newGasLeft := add(evmGasLeft, frameGasLeft) diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 20897c518..d0d4bbfaa 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -1425,13 +1425,7 @@ for { } true { } { } case 0xF1 { // OP_CALL // A function was implemented in order to avoid stack depth errors. - switch isStatic - case 0 { - evmGasLeft, sp, stackHead := performCall(sp, evmGasLeft, stackHead) - } - default { - evmGasLeft, sp, stackHead := performStaticCall(sp, evmGasLeft, stackHead) - } + evmGasLeft, sp, stackHead := performCall(sp, evmGasLeft, stackHead, isStatic) ip := add(ip, 1) } case 0xF3 { // OP_RETURN From 18186267dcf3f551951253a150350f4867ac1f2c Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 27 Nov 2024 17:49:17 +0100 Subject: [PATCH 159/183] fix(EVM): Fix calls to contract being created (#1093) --- system-contracts/contracts/EvmEmulator.yul | 18 ++++++++++++++++-- .../EvmEmulatorFunctions.template.yul | 9 ++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index fea544e05..3d754f38f 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -390,6 +390,13 @@ object "EvmEmulator" { isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } + function isConstructedEvmContract(addr) -> isConstructedEVM { + let rawCodeHash := getRawCodeHash(addr) + let version := shr(248, rawCodeHash) + let isConstructedFlag := xor(shr(240, rawCodeHash), 1) + isConstructedEVM := and(eq(version, 2), isConstructedFlag) + } + // Basically performs an extcodecopy, while returning the length of the copied bytecode. function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) @@ -803,7 +810,7 @@ object "EvmEmulator" { } function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - switch isEvmContract(addr) + switch isConstructedEvmContract(addr) case 0 { // zkEVM native call let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) @@ -3415,6 +3422,13 @@ object "EvmEmulator" { isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } + function isConstructedEvmContract(addr) -> isConstructedEVM { + let rawCodeHash := getRawCodeHash(addr) + let version := shr(248, rawCodeHash) + let isConstructedFlag := xor(shr(240, rawCodeHash), 1) + isConstructedEVM := and(eq(version, 2), isConstructedFlag) + } + // Basically performs an extcodecopy, while returning the length of the copied bytecode. function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) @@ -3828,7 +3842,7 @@ object "EvmEmulator" { } function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - switch isEvmContract(addr) + switch isConstructedEvmContract(addr) case 0 { // zkEVM native call let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 81b2d84ac..d8131e1a8 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -328,6 +328,13 @@ function isEvmContract(addr) -> isEVM { isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } +function isConstructedEvmContract(addr) -> isConstructedEVM { + let rawCodeHash := getRawCodeHash(addr) + let version := shr(248, rawCodeHash) + let isConstructedFlag := xor(shr(240, rawCodeHash), 1) + isConstructedEVM := and(eq(version, 2), isConstructedFlag) +} + // Basically performs an extcodecopy, while returning the length of the copied bytecode. function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) @@ -741,7 +748,7 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGa } function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - switch isEvmContract(addr) + switch isConstructedEvmContract(addr) case 0 { // zkEVM native call let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) From 12efa1c00fbfbd4de7b919438010f5af75750902 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 28 Nov 2024 13:49:35 +0100 Subject: [PATCH 160/183] fix(EVM): Wrap access to calldata to prevent out-of-bounds EraVM panic (#1097) --- system-contracts/contracts/EvmEmulator.yul | 86 +++++++++++++------ .../evm-emulator/EvmEmulatorLoop.template.yul | 43 +++++++--- 2 files changed, 93 insertions(+), 36 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 3d754f38f..ad827c5bb 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1552,7 +1552,13 @@ object "EvmEmulator" { case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) - stackHead := calldataload(accessStackHead(sp, stackHead)) + let calldataOffset := accessStackHead(sp, stackHead) + + stackHead := 0 + // EraVM will revert if offset + length overflows uint32 + if lt(calldataOffset, UINT32_MAX()) { + stackHead := calldataload(calldataOffset) + } ip := add(ip, 1) } @@ -1565,25 +1571,38 @@ object "EvmEmulator" { case 0x37 { // OP_CALLDATACOPY evmGasLeft := chargeGas(evmGasLeft, 3) - let destOffset, offset, size + let dstOffset, sourceOffset, len popStackCheck(sp, 3) - destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(destOffset, size) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + sourceOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - if gt(offset, MAX_UINT64()) { - offset := MAX_UINT64() - } + checkMemIsAccessible(dstOffset, len) // 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(destOffset, size)) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - calldatacopy(add(destOffset, MEM_OFFSET()), offset, size) + dstOffset := add(dstOffset, MEM_OFFSET()) + + // EraVM will revert if offset + length overflows uint32 + if gt(sourceOffset, UINT32_MAX()) { + sourceOffset := UINT32_MAX() + } + + // Check bytecode out-of-bounds access + let truncatedLen := len + if gt(add(sourceOffset, len), UINT32_MAX()) { + truncatedLen := sub(UINT32_MAX(), sourceOffset) // truncate + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, truncatedLen), sub(len, truncatedLen)) // pad with zeroes any out-of-bounds + } + + if truncatedLen { + calldatacopy(dstOffset, sourceOffset, truncatedLen) + } + ip := add(ip, 1) } @@ -4584,7 +4603,13 @@ object "EvmEmulator" { case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) - stackHead := calldataload(accessStackHead(sp, stackHead)) + let calldataOffset := accessStackHead(sp, stackHead) + + stackHead := 0 + // EraVM will revert if offset + length overflows uint32 + if lt(calldataOffset, UINT32_MAX()) { + stackHead := calldataload(calldataOffset) + } ip := add(ip, 1) } @@ -4597,25 +4622,38 @@ object "EvmEmulator" { case 0x37 { // OP_CALLDATACOPY evmGasLeft := chargeGas(evmGasLeft, 3) - let destOffset, offset, size + let dstOffset, sourceOffset, len popStackCheck(sp, 3) - destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(destOffset, size) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + sourceOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - if gt(offset, MAX_UINT64()) { - offset := MAX_UINT64() - } + checkMemIsAccessible(dstOffset, len) // 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(destOffset, size)) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - calldatacopy(add(destOffset, MEM_OFFSET()), offset, size) + dstOffset := add(dstOffset, MEM_OFFSET()) + + // EraVM will revert if offset + length overflows uint32 + if gt(sourceOffset, UINT32_MAX()) { + sourceOffset := UINT32_MAX() + } + + // Check bytecode out-of-bounds access + let truncatedLen := len + if gt(add(sourceOffset, len), UINT32_MAX()) { + truncatedLen := sub(UINT32_MAX(), sourceOffset) // truncate + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, truncatedLen), sub(len, truncatedLen)) // pad with zeroes any out-of-bounds + } + + if truncatedLen { + calldatacopy(dstOffset, sourceOffset, truncatedLen) + } + ip := add(ip, 1) } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index d0d4bbfaa..0c3196a9e 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -339,7 +339,13 @@ for { } true { } { case 0x35 { // OP_CALLDATALOAD evmGasLeft := chargeGas(evmGasLeft, 3) - stackHead := calldataload(accessStackHead(sp, stackHead)) + let calldataOffset := accessStackHead(sp, stackHead) + + stackHead := 0 + // EraVM will revert if offset + length overflows uint32 + if lt(calldataOffset, UINT32_MAX()) { + stackHead := calldataload(calldataOffset) + } ip := add(ip, 1) } @@ -352,25 +358,38 @@ for { } true { } { case 0x37 { // OP_CALLDATACOPY evmGasLeft := chargeGas(evmGasLeft, 3) - let destOffset, offset, size + let dstOffset, sourceOffset, len popStackCheck(sp, 3) - destOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - offset, sp, stackHead:= popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(destOffset, size) + dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + sourceOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - if gt(offset, MAX_UINT64()) { - offset := MAX_UINT64() - } + checkMemIsAccessible(dstOffset, len) // 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(destOffset, size)) + let dynamicGas := add(mul(3, shr(5, add(len, 31))), expandMemory(dstOffset, len)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - calldatacopy(add(destOffset, MEM_OFFSET()), offset, size) + dstOffset := add(dstOffset, MEM_OFFSET()) + + // EraVM will revert if offset + length overflows uint32 + if gt(sourceOffset, UINT32_MAX()) { + sourceOffset := UINT32_MAX() + } + + // Check bytecode out-of-bounds access + let truncatedLen := len + if gt(add(sourceOffset, len), UINT32_MAX()) { + truncatedLen := sub(UINT32_MAX(), sourceOffset) // truncate + $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, truncatedLen), sub(len, truncatedLen)) // pad with zeroes any out-of-bounds + } + + if truncatedLen { + calldatacopy(dstOffset, sourceOffset, truncatedLen) + } + ip := add(ip, 1) } From 07f43d04ae5a76c08a264c201953341269eb45e6 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 28 Nov 2024 19:08:50 +0100 Subject: [PATCH 161/183] fix(EVM): Zero out frame gas left for underpaid precompiles (#1101) --- system-contracts/contracts/EvmEmulator.yul | 2 ++ system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul | 1 + 2 files changed, 3 insertions(+) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index ad827c5bb..e3803ce7f 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -839,6 +839,7 @@ object "EvmEmulator" { let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts if lt(gasToPass, precompileCost) { zkVmGasToPass := 0 // in EVM precompile should revert consuming all gas in that case + precompileCost := gasToPass // just in case } switch isStatic @@ -3890,6 +3891,7 @@ object "EvmEmulator" { let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts if lt(gasToPass, precompileCost) { zkVmGasToPass := 0 // in EVM precompile should revert consuming all gas in that case + precompileCost := gasToPass // just in case } switch isStatic diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index d8131e1a8..b8b4a8448 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -777,6 +777,7 @@ function callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, args let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts if lt(gasToPass, precompileCost) { zkVmGasToPass := 0 // in EVM precompile should revert consuming all gas in that case + precompileCost := gasToPass // just in case } switch isStatic From c74c6ecc2db289fb33f7c88f0fa353b92cce94d9 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 2 Dec 2024 15:22:31 +0100 Subject: [PATCH 162/183] fix(EVM): Fix panics on insufficient balance in calls (#1108) --- system-contracts/contracts/EvmEmulator.yul | 64 ++++++++++++------- .../EvmEmulatorFunctions.template.yul | 32 ++++++---- 2 files changed, 60 insertions(+), 36 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index e3803ce7f..0f0d6b15d 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -293,6 +293,12 @@ object "EvmEmulator" { } } + function insufficientBalance(value) -> res { + if value { + res := gt(value, selfbalance()) + } + } + // It is the responsibility of the caller to ensure that ip is correct function readIP(ip, bytecodeEndOffset) -> opcode { if lt(ip, bytecodeEndOffset) { @@ -825,12 +831,19 @@ object "EvmEmulator" { } } default { - pushEvmFrame(gasToPass, isStatic) - // pass all remaining native gas - success := call(gas(), addr, value, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - if iszero(success) { - resetEvmFrame() + switch insufficientBalance(value) + case 0 { + pushEvmFrame(gasToPass, isStatic) + // pass all remaining native gas + success := call(gas(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + if iszero(success) { + resetEvmFrame() + } + } + default { + frameGasLeft := gasToPass + _eraseReturndataPointer() } } } @@ -1042,12 +1055,7 @@ object "EvmEmulator" { _eraseReturndataPointer() - let err := 0 - if value { - if gt(value, selfbalance()) { - err := 1 - } - } + let err := insufficientBalance(value) if iszero(err) { offset := add(MEM_OFFSET(), offset) // caller must ensure that it doesn't overflow @@ -3345,6 +3353,12 @@ object "EvmEmulator" { } } + function insufficientBalance(value) -> res { + if value { + res := gt(value, selfbalance()) + } + } + // It is the responsibility of the caller to ensure that ip is correct function readIP(ip, bytecodeEndOffset) -> opcode { if lt(ip, bytecodeEndOffset) { @@ -3877,12 +3891,19 @@ object "EvmEmulator" { } } default { - pushEvmFrame(gasToPass, isStatic) - // pass all remaining native gas - success := call(gas(), addr, value, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - if iszero(success) { - resetEvmFrame() + switch insufficientBalance(value) + case 0 { + pushEvmFrame(gasToPass, isStatic) + // pass all remaining native gas + success := call(gas(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + if iszero(success) { + resetEvmFrame() + } + } + default { + frameGasLeft := gasToPass + _eraseReturndataPointer() } } } @@ -4094,12 +4115,7 @@ object "EvmEmulator" { _eraseReturndataPointer() - let err := 0 - if value { - if gt(value, selfbalance()) { - err := 1 - } - } + let err := insufficientBalance(value) if iszero(err) { offset := add(MEM_OFFSET(), offset) // caller must ensure that it doesn't overflow diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index b8b4a8448..bd62c2600 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -231,6 +231,12 @@ function checkOverflow(data1, data2) { } } +function insufficientBalance(value) -> res { + if value { + res := gt(value, selfbalance()) + } +} + // It is the responsibility of the caller to ensure that ip is correct function readIP(ip, bytecodeEndOffset) -> opcode { if lt(ip, bytecodeEndOffset) { @@ -763,12 +769,19 @@ function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, r } } default { - pushEvmFrame(gasToPass, isStatic) - // pass all remaining native gas - success := call(gas(), addr, value, argsOffset, argsSize, 0, 0) - frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) - if iszero(success) { - resetEvmFrame() + switch insufficientBalance(value) + case 0 { + pushEvmFrame(gasToPass, isStatic) + // pass all remaining native gas + success := call(gas(), addr, value, argsOffset, argsSize, 0, 0) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + if iszero(success) { + resetEvmFrame() + } + } + default { + frameGasLeft := gasToPass + _eraseReturndataPointer() } } } @@ -980,12 +993,7 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, _eraseReturndataPointer() - let err := 0 - if value { - if gt(value, selfbalance()) { - err := 1 - } - } + let err := insufficientBalance(value) if iszero(err) { offset := add(MEM_OFFSET(), offset) // caller must ensure that it doesn't overflow From 5869331d0c742a771316af212faa1e5a27cf8c03 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 2 Dec 2024 16:55:09 +0100 Subject: [PATCH 163/183] fix(EVM): Fix DUP1 underflow check (#1110) --- system-contracts/contracts/EvmEmulator.yul | 4 ++-- system-contracts/evm-emulator/EvmEmulatorLoop.template.yul | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 0f0d6b15d..a966924bb 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -2396,7 +2396,7 @@ object "EvmEmulator" { } case 0x80 { // OP_DUP1 evmGasLeft := chargeGas(evmGasLeft, 3) - sp, stackHead := pushStackItem(sp, stackHead, stackHead) + sp, stackHead := pushStackItem(sp, accessStackHead(sp, stackHead), stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 @@ -5456,7 +5456,7 @@ object "EvmEmulator" { } case 0x80 { // OP_DUP1 evmGasLeft := chargeGas(evmGasLeft, 3) - sp, stackHead := pushStackItem(sp, stackHead, stackHead) + sp, stackHead := pushStackItem(sp, accessStackHead(sp, stackHead), stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 0c3196a9e..c1ba325c1 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -1174,7 +1174,7 @@ for { } true { } { } case 0x80 { // OP_DUP1 evmGasLeft := chargeGas(evmGasLeft, 3) - sp, stackHead := pushStackItem(sp, stackHead, stackHead) + sp, stackHead := pushStackItem(sp, accessStackHead(sp, stackHead), stackHead) ip := add(ip, 1) } case 0x81 { // OP_DUP2 From 55367f570cb699d36fe140527b208443479063dc Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Tue, 3 Dec 2024 10:49:37 +0100 Subject: [PATCH 164/183] fix(EVM): Update LLVM options after fixes (#1112) Signed-off-by: Vladimir Radosavljevic Co-authored-by: Vladimir Radosavljevic --- system-contracts/contracts/EvmEmulator.yul.llvm.options | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system-contracts/contracts/EvmEmulator.yul.llvm.options b/system-contracts/contracts/EvmEmulator.yul.llvm.options index ea418b985..704e0a70e 100644 --- a/system-contracts/contracts/EvmEmulator.yul.llvm.options +++ b/system-contracts/contracts/EvmEmulator.yul.llvm.options @@ -1 +1 @@ -'-eravm-jump-table-density-threshold=10 -tail-dup-size=6 -eravm-enable-split-loop-phi-live-ranges -tail-merge-only-bbs-without-succ -join-globalcopies -disable-early-taildup' \ No newline at end of file +'-eravm-jump-table-density-threshold=10 -tail-dup-size=6 -eravm-enable-split-loop-phi-live-ranges -tail-merge-only-bbs-without-succ -tail-dup-fallthrough-bbs' \ No newline at end of file From 70d1de865e264550a62e0862bdb1f57908938a7d Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 4 Dec 2024 13:54:22 +0100 Subject: [PATCH 165/183] fix(EVM): Do not check memory boundaries if size is zero (#1114) --- system-contracts/contracts/EvmEmulator.yul | 84 ++++++++++++------- .../EvmEmulatorFunctions.template.yul | 8 +- .../evm-emulator/EvmEmulatorLoop.template.yul | 34 +++++--- 3 files changed, 81 insertions(+), 45 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index a966924bb..968ab3b38 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -280,10 +280,12 @@ object "EvmEmulator" { } function checkMemIsAccessible(relativeOffset, size) { - checkOverflow(relativeOffset, size) + if size { + checkOverflow(relativeOffset, size) - if gt(add(relativeOffset, size), MAX_POSSIBLE_MEM_LEN()) { - panic() + if gt(add(relativeOffset, size), MAX_POSSIBLE_MEM_LEN()) { + panic() + } } } @@ -2676,14 +2678,17 @@ object "EvmEmulator" { offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(offset, size) + if size { + checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) + + returnLen := size + + // Don't check overflow here since previous checks are enough to ensure this is safe + returnOffset := add(MEM_OFFSET(), offset) + } - returnLen := size - - // Don't check overflow here since previous checks are enough to ensure this is safe - returnOffset := add(MEM_OFFSET(), offset) break } case 0xF4 { // OP_DELEGATECALL @@ -2710,12 +2715,19 @@ object "EvmEmulator" { popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) - - // Don't check overflow here since previous checks are enough to ensure this is safe - offset := add(offset, MEM_OFFSET()) + + switch iszero(size) + case 0 { + checkMemIsAccessible(offset, size) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) + + // Don't check overflow here since previous checks are enough to ensure this is safe + offset := add(offset, MEM_OFFSET()) + } + default { + offset := MEM_OFFSET() + } + if eq(isCallerEVM, 1) { offset := sub(offset, 32) @@ -3340,10 +3352,12 @@ object "EvmEmulator" { } function checkMemIsAccessible(relativeOffset, size) { - checkOverflow(relativeOffset, size) + if size { + checkOverflow(relativeOffset, size) - if gt(add(relativeOffset, size), MAX_POSSIBLE_MEM_LEN()) { - panic() + if gt(add(relativeOffset, size), MAX_POSSIBLE_MEM_LEN()) { + panic() + } } } @@ -5736,14 +5750,17 @@ object "EvmEmulator" { offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(offset, size) + if size { + checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) + + returnLen := size + + // Don't check overflow here since previous checks are enough to ensure this is safe + returnOffset := add(MEM_OFFSET(), offset) + } - returnLen := size - - // Don't check overflow here since previous checks are enough to ensure this is safe - returnOffset := add(MEM_OFFSET(), offset) break } case 0xF4 { // OP_DELEGATECALL @@ -5770,12 +5787,19 @@ object "EvmEmulator" { popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) - - // Don't check overflow here since previous checks are enough to ensure this is safe - offset := add(offset, MEM_OFFSET()) + + switch iszero(size) + case 0 { + checkMemIsAccessible(offset, size) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) + + // Don't check overflow here since previous checks are enough to ensure this is safe + offset := add(offset, MEM_OFFSET()) + } + default { + offset := MEM_OFFSET() + } + if eq(isCallerEVM, 1) { offset := sub(offset, 32) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index bd62c2600..345e13b82 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -218,10 +218,12 @@ function expandMemory2(retOffset, retSize, argsOffset, argsSize) -> maxExpand { } function checkMemIsAccessible(relativeOffset, size) { - checkOverflow(relativeOffset, size) + if size { + checkOverflow(relativeOffset, size) - if gt(add(relativeOffset, size), MAX_POSSIBLE_MEM_LEN()) { - panic() + if gt(add(relativeOffset, size), MAX_POSSIBLE_MEM_LEN()) { + panic() + } } } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index c1ba325c1..4b817b149 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -1454,14 +1454,17 @@ for { } true { } { offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(offset, size) + if size { + checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) + + returnLen := size + + // Don't check overflow here since previous checks are enough to ensure this is safe + returnOffset := add(MEM_OFFSET(), offset) + } - returnLen := size - - // Don't check overflow here since previous checks are enough to ensure this is safe - returnOffset := add(MEM_OFFSET(), offset) break } case 0xF4 { // OP_DELEGATECALL @@ -1488,12 +1491,19 @@ for { } true { } { popStackCheck(sp, 2) offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) - - // Don't check overflow here since previous checks are enough to ensure this is safe - offset := add(offset, MEM_OFFSET()) + + switch iszero(size) + case 0 { + checkMemIsAccessible(offset, size) + evmGasLeft := chargeGas(evmGasLeft, expandMemory(offset, size)) + + // Don't check overflow here since previous checks are enough to ensure this is safe + offset := add(offset, MEM_OFFSET()) + } + default { + offset := MEM_OFFSET() + } + if eq(isCallerEVM, 1) { offset := sub(offset, 32) From 37874c76783aaab54dc28136c7090b09fc98a878 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 4 Dec 2024 14:46:51 +0100 Subject: [PATCH 166/183] fi(EVM): Fix EXTCODECOPY zeroing offset (#1115) --- system-contracts/contracts/EvmEmulator.yul | 8 ++++++-- .../evm-emulator/EvmEmulatorLoop.template.yul | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 968ab3b38..8f48f4eaf 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1717,6 +1717,8 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + dstOffset := add(dstOffset, MEM_OFFSET()) + if gt(srcOffset, MAX_UINT64()) { srcOffset := MAX_UINT64() } @@ -1725,7 +1727,7 @@ object "EvmEmulator" { let copiedLen if getRawCodeHash(addr) { // Gets the code from the addr - copiedLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) + copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) } if lt(copiedLen, len) { @@ -4789,6 +4791,8 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + dstOffset := add(dstOffset, MEM_OFFSET()) + if gt(srcOffset, MAX_UINT64()) { srcOffset := MAX_UINT64() } @@ -4797,7 +4801,7 @@ object "EvmEmulator" { let copiedLen if getRawCodeHash(addr) { // Gets the code from the addr - copiedLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) + copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) } if lt(copiedLen, len) { diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 4b817b149..fc8d28827 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -493,6 +493,8 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + dstOffset := add(dstOffset, MEM_OFFSET()) + if gt(srcOffset, MAX_UINT64()) { srcOffset := MAX_UINT64() } @@ -501,7 +503,7 @@ for { } true { } { let copiedLen if getRawCodeHash(addr) { // Gets the code from the addr - copiedLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len) + copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) } if lt(copiedLen, len) { From 6a76d761f07174fd5f3c62a34a6c72e34ac09480 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 4 Dec 2024 18:26:19 +0100 Subject: [PATCH 167/183] fix(EVM): Cleanup address bytes in EXTCODECOPY (#1116) --- system-contracts/contracts/EvmEmulator.yul | 4 ++++ system-contracts/evm-emulator/EvmEmulatorLoop.template.yul | 2 ++ 2 files changed, 6 insertions(+) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 8f48f4eaf..9e76b5358 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1701,6 +1701,8 @@ object "EvmEmulator" { dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) srcOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) checkMemIsAccessible(dstOffset, len) @@ -4775,6 +4777,8 @@ object "EvmEmulator" { dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) srcOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) checkMemIsAccessible(dstOffset, len) diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index fc8d28827..20cdc0a2f 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -477,6 +477,8 @@ for { } true { } { dstOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) srcOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) len, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + + addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) checkMemIsAccessible(dstOffset, len) From 2bdc565526efb347384e95f1ba2a477b06f88d58 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 5 Dec 2024 17:35:42 +0100 Subject: [PATCH 168/183] fix(EVM): Use raw calls to precompiles (#1118) --- system-contracts/contracts/EvmEmulator.yul | 126 ++++++++++++------ .../EvmEmulatorFunctions.template.yul | 63 ++++++--- 2 files changed, 132 insertions(+), 57 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 9e76b5358..2fb6ad8cc 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -463,6 +463,16 @@ object "EvmEmulator" { } } + function build_farcall_abi(isSystemCall, gas, dataStart, dataLength) -> farCallAbi { + farCallAbi := shl(248, isSystemCall) + // dataOffset is 0 + farCallAbi := or(farCallAbi, shl(64, dataStart)) + farCallAbi := or(farCallAbi, shl(96, dataLength)) + farCallAbi := or(farCallAbi, shl(192, gas)) + // shardId is 0 + // forwardingMode is 0 + } + function performSystemCall(to, dataLength) { let success := performSystemCallRevertable(to, dataLength) @@ -473,18 +483,39 @@ object "EvmEmulator" { } function performSystemCallRevertable(to, dataLength) -> success { - let farCallAbi := shl(248, 1) // system call - // dataOffset is 0 - // dataStart is 0 - farCallAbi := or(farCallAbi, shl(96, dataLength)) - farCallAbi := or(farCallAbi, shl(192, gas())) - // shardId is 0 - // forwardingMode is 0 - // not constructor call - + // system call, dataStart is 0 + let farCallAbi := build_farcall_abi(1, gas(), 0, dataLength) success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } + function rawCall(gas, to, value, dataStart, dataLength, outputOffset, outputLen) -> success { + switch iszero(value) + case 0 { + // system call to MsgValueSimulator, but call to "to" will be non-system + let farCallAbi := build_farcall_abi(1, gas, dataStart, dataLength) + success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, to, 0, 0) + if outputLen { + if success { + let rtdz := returndatasize() + switch lt(rtdz, outputLen) + case 0 { returndatacopy(outputOffset, 0, outputLen) } + default { returndatacopy(outputOffset, 0, rtdz) } + } + } + } + default { + // not a system call + let farCallAbi := build_farcall_abi(0, gas, dataStart, dataLength) + success := verbatim_4i_1o("raw_call", to, farCallAbi, outputOffset, outputLen) + } + } + + function rawStaticcall(gas, to, dataStart, dataLength, outputOffset, outputLen) -> success { + // not a system call + let farCallAbi := build_farcall_abi(0, gas, dataStart, dataLength) + success := verbatim_4i_1o("raw_static_call", to, farCallAbi, outputOffset, outputLen) + } + //////////////////////////////////////////////////////////////// // STACK OPERATIONS //////////////////////////////////////////////////////////////// @@ -859,10 +890,10 @@ object "EvmEmulator" { switch isStatic case 0 { - success := call(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + success := rawCall(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) } default { - success := staticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) + success := rawStaticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) } _saveReturndataAfterZkEVMCall() @@ -1136,14 +1167,8 @@ object "EvmEmulator" { } function performSystemCallForCreate(value, bytecodeStart, bytecodeLen) -> success { - let farCallAbi := shl(248, 1) // system call - // dataOffset is 0 - farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) - farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) - farCallAbi := or(farCallAbi, shl(192, gas())) - // shardId is 0 - // forwardingMode is 0 - // not constructor call (ContractDeployer will call constructor) + // system call, not constructor call (ContractDeployer will call constructor) + let farCallAbi := build_farcall_abi(1, gas(), bytecodeStart, bytecodeLen) switch iszero(value) case 0 { @@ -3539,6 +3564,16 @@ object "EvmEmulator" { } } + function build_farcall_abi(isSystemCall, gas, dataStart, dataLength) -> farCallAbi { + farCallAbi := shl(248, isSystemCall) + // dataOffset is 0 + farCallAbi := or(farCallAbi, shl(64, dataStart)) + farCallAbi := or(farCallAbi, shl(96, dataLength)) + farCallAbi := or(farCallAbi, shl(192, gas)) + // shardId is 0 + // forwardingMode is 0 + } + function performSystemCall(to, dataLength) { let success := performSystemCallRevertable(to, dataLength) @@ -3549,18 +3584,39 @@ object "EvmEmulator" { } function performSystemCallRevertable(to, dataLength) -> success { - let farCallAbi := shl(248, 1) // system call - // dataOffset is 0 - // dataStart is 0 - farCallAbi := or(farCallAbi, shl(96, dataLength)) - farCallAbi := or(farCallAbi, shl(192, gas())) - // shardId is 0 - // forwardingMode is 0 - // not constructor call - + // system call, dataStart is 0 + let farCallAbi := build_farcall_abi(1, gas(), 0, dataLength) success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } + function rawCall(gas, to, value, dataStart, dataLength, outputOffset, outputLen) -> success { + switch iszero(value) + case 0 { + // system call to MsgValueSimulator, but call to "to" will be non-system + let farCallAbi := build_farcall_abi(1, gas, dataStart, dataLength) + success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, to, 0, 0) + if outputLen { + if success { + let rtdz := returndatasize() + switch lt(rtdz, outputLen) + case 0 { returndatacopy(outputOffset, 0, outputLen) } + default { returndatacopy(outputOffset, 0, rtdz) } + } + } + } + default { + // not a system call + let farCallAbi := build_farcall_abi(0, gas, dataStart, dataLength) + success := verbatim_4i_1o("raw_call", to, farCallAbi, outputOffset, outputLen) + } + } + + function rawStaticcall(gas, to, dataStart, dataLength, outputOffset, outputLen) -> success { + // not a system call + let farCallAbi := build_farcall_abi(0, gas, dataStart, dataLength) + success := verbatim_4i_1o("raw_static_call", to, farCallAbi, outputOffset, outputLen) + } + //////////////////////////////////////////////////////////////// // STACK OPERATIONS //////////////////////////////////////////////////////////////// @@ -3935,10 +3991,10 @@ object "EvmEmulator" { switch isStatic case 0 { - success := call(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + success := rawCall(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) } default { - success := staticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) + success := rawStaticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) } _saveReturndataAfterZkEVMCall() @@ -4212,14 +4268,8 @@ object "EvmEmulator" { } function performSystemCallForCreate(value, bytecodeStart, bytecodeLen) -> success { - let farCallAbi := shl(248, 1) // system call - // dataOffset is 0 - farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) - farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) - farCallAbi := or(farCallAbi, shl(192, gas())) - // shardId is 0 - // forwardingMode is 0 - // not constructor call (ContractDeployer will call constructor) + // system call, not constructor call (ContractDeployer will call constructor) + let farCallAbi := build_farcall_abi(1, gas(), bytecodeStart, bytecodeLen) switch iszero(value) case 0 { diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 345e13b82..bb0c602db 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -401,6 +401,16 @@ function getMax(a, b) -> max { } } +function build_farcall_abi(isSystemCall, gas, dataStart, dataLength) -> farCallAbi { + farCallAbi := shl(248, isSystemCall) + // dataOffset is 0 + farCallAbi := or(farCallAbi, shl(64, dataStart)) + farCallAbi := or(farCallAbi, shl(96, dataLength)) + farCallAbi := or(farCallAbi, shl(192, gas)) + // shardId is 0 + // forwardingMode is 0 +} + function performSystemCall(to, dataLength) { let success := performSystemCallRevertable(to, dataLength) @@ -411,18 +421,39 @@ function performSystemCall(to, dataLength) { } function performSystemCallRevertable(to, dataLength) -> success { - let farCallAbi := shl(248, 1) // system call - // dataOffset is 0 - // dataStart is 0 - farCallAbi := or(farCallAbi, shl(96, dataLength)) - farCallAbi := or(farCallAbi, shl(192, gas())) - // shardId is 0 - // forwardingMode is 0 - // not constructor call - + // system call, dataStart is 0 + let farCallAbi := build_farcall_abi(1, gas(), 0, dataLength) success := verbatim_6i_1o("system_call", to, farCallAbi, 0, 0, 0, 0) } +function rawCall(gas, to, value, dataStart, dataLength, outputOffset, outputLen) -> success { + switch iszero(value) + case 0 { + // system call to MsgValueSimulator, but call to "to" will be non-system + let farCallAbi := build_farcall_abi(1, gas, dataStart, dataLength) + success := verbatim_6i_1o("system_call", MSG_VALUE_SYSTEM_CONTRACT(), farCallAbi, value, to, 0, 0) + if outputLen { + if success { + let rtdz := returndatasize() + switch lt(rtdz, outputLen) + case 0 { returndatacopy(outputOffset, 0, outputLen) } + default { returndatacopy(outputOffset, 0, rtdz) } + } + } + } + default { + // not a system call + let farCallAbi := build_farcall_abi(0, gas, dataStart, dataLength) + success := verbatim_4i_1o("raw_call", to, farCallAbi, outputOffset, outputLen) + } +} + +function rawStaticcall(gas, to, dataStart, dataLength, outputOffset, outputLen) -> success { + // not a system call + let farCallAbi := build_farcall_abi(0, gas, dataStart, dataLength) + success := verbatim_4i_1o("raw_static_call", to, farCallAbi, outputOffset, outputLen) +} + //////////////////////////////////////////////////////////////// // STACK OPERATIONS //////////////////////////////////////////////////////////////// @@ -797,10 +828,10 @@ function callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, args switch isStatic case 0 { - success := call(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + success := rawCall(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) } default { - success := staticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) + success := rawStaticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) } _saveReturndataAfterZkEVMCall() @@ -1074,14 +1105,8 @@ function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> } function performSystemCallForCreate(value, bytecodeStart, bytecodeLen) -> success { - let farCallAbi := shl(248, 1) // system call - // dataOffset is 0 - farCallAbi := or(farCallAbi, shl(64, bytecodeStart)) - farCallAbi := or(farCallAbi, shl(96, bytecodeLen)) - farCallAbi := or(farCallAbi, shl(192, gas())) - // shardId is 0 - // forwardingMode is 0 - // not constructor call (ContractDeployer will call constructor) + // system call, not constructor call (ContractDeployer will call constructor) + let farCallAbi := build_farcall_abi(1, gas(), bytecodeStart, bytecodeLen) switch iszero(value) case 0 { From 3299faa649f389b6f3b9855b573e2654206f6c10 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 5 Dec 2024 20:09:47 +0100 Subject: [PATCH 169/183] fix(EVM): Make DELEGATECALL behavior closer to EVM (3) (#1120) --- system-contracts/contracts/EvmEmulator.yul | 272 +++++++++--------- .../EvmEmulatorFunctions.template.yul | 136 ++++----- 2 files changed, 207 insertions(+), 201 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 2fb6ad8cc..c62b333da 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -398,8 +398,7 @@ object "EvmEmulator" { isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } - function isConstructedEvmContract(addr) -> isConstructedEVM { - let rawCodeHash := getRawCodeHash(addr) + function isHashOfConstructedEvmContract(rawCodeHash) -> isConstructedEVM { let version := shr(248, rawCodeHash) let isConstructedFlag := xor(shr(240, rawCodeHash), 1) isConstructedEVM := and(eq(version, 2), isConstructedFlag) @@ -688,21 +687,16 @@ object "EvmEmulator" { //////////////////////////////////////////////////////////////// function performCall(oldSp, evmGasLeft, oldStackHead, isStatic) -> newGasLeft, sp, stackHead { - let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize + let gasToPass, rawAddr, value, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 7) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawAddr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) - addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - - checkMemIsAccessible(argsOffset, argsSize) - checkMemIsAccessible(retOffset, retSize) - // 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). @@ -710,13 +704,7 @@ object "EvmEmulator" { // 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. // 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. - let gasUsed := 100 // warm address access cost - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 // cold address access cost - } - - // memory_expansion_cost - gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) + let addr, gasUsed := _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) if gt(value, 0) { if isStatic { @@ -754,27 +742,16 @@ object "EvmEmulator" { } function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { - let gasToPass,addr, argsOffset, argsSize, retOffset, retSize + let gasToPass, rawAddr, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawAddr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) - addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - - checkMemIsAccessible(argsOffset, argsSize) - checkMemIsAccessible(retOffset, retSize) - - let gasUsed := 100 // warm address access cost - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 // cold address access cost - } - - // memory_expansion_cost - gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) + let addr, gasUsed := _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) evmGasLeft := chargeGas(evmGasLeft, gasUsed) gasToPass := capGasForCall(evmGasLeft, gasToPass) @@ -797,62 +774,88 @@ object "EvmEmulator" { function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGasLeft, sp, stackHead { - let addr, gasToPass, argsOffset, argsSize, retOffset, retSize + let gasToPass, rawAddr, rawArgsOffset, argsSize, rawRetOffset, retSize popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawAddr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawArgsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) + rawRetOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) - addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + let addr, gasUsed := _genericPrecallLogic(rawAddr, rawArgsOffset, argsSize, rawRetOffset, retSize) - checkMemIsAccessible(argsOffset, argsSize) - checkMemIsAccessible(retOffset, retSize) + newGasLeft := chargeGas(evmGasLeft, gasUsed) + gasToPass := capGasForCall(newGasLeft, gasToPass) - let gasUsed := 100 // warm address access cost - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 // cold address access cost - } + newGasLeft := sub(newGasLeft, gasToPass) - // memory_expansion_cost - gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) + let success + let frameGasLeft := gasToPass - evmGasLeft := chargeGas(evmGasLeft, gasUsed) + let retOffset := add(MEM_OFFSET(), rawRetOffset) + let argsOffset := add(MEM_OFFSET(), rawArgsOffset) - // it is also not possible to delegatecall precompiles - if iszero(isEvmContract(addr)) { - revertWithGas(evmGasLeft) + let rawCodeHash := getRawCodeHash(addr) + switch isHashOfConstructedEvmContract(rawCodeHash) + case 0 { + // Not a constructed EVM contract + let precompileCost := getGasForPrecompiles(addr, argsSize) + switch precompileCost + case 0 { + // Not a precompile + switch eq(1, shr(248, rawCodeHash)) + case 0 { + // Empty contract or EVM contract being constructed + success := delegatecall(gas(), addr, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + } + default { + // We forbid delegatecalls to EraVM native contracts + _eraseReturndataPointer() + } + } + default { + // Precompile. Simlate using staticcall, since EraVM behavior differs here + success, frameGasLeft := callPrecompile(addr, precompileCost, gasToPass, 0, argsOffset, argsSize, retOffset, retSize, true) + } } + default { + // Constructed EVM contract + pushEvmFrame(gasToPass, isStatic) + // pass all remaining native gas + success := delegatecall(gas(), addr, argsOffset, argsSize, 0, 0) - gasToPass := capGasForCall(evmGasLeft, gasToPass) - evmGasLeft := sub(evmGasLeft, gasToPass) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + if iszero(success) { + resetEvmFrame() + } + } - pushEvmFrame(gasToPass, isStatic) - let success := delegatecall( - gas(), // pass all remaining native gas - addr, - add(MEM_OFFSET(), argsOffset), - argsSize, - 0, - 0 - ) + newGasLeft := add(newGasLeft, frameGasLeft) + stackHead := success + } - let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET(), retOffset), retSize) - if iszero(success) { - resetEvmFrame() + function _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) -> addr, gasUsed { + addr := and(rawAddr, 0xffffffffffffffffffffffffffffffffffffffff) + + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) + + gasUsed := 100 // warm address access cost + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + gasUsed := 2600 // cold address access cost } - newGasLeft := add(evmGasLeft, frameGasLeft) - stackHead := success + // memory_expansion_cost + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) } function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - switch isConstructedEvmContract(addr) + switch isHashOfConstructedEvmContract(getRawCodeHash(addr)) case 0 { // zkEVM native call - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + let precompileCost := getGasForPrecompiles(addr, argsSize) switch precompileCost case 0 { // just smart contract @@ -945,8 +948,7 @@ object "EvmEmulator" { // 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() when passing the argsOffset - function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { + function getGasForPrecompiles(addr, argsSize) -> gasToCharge { switch addr case 0x01 { // ecRecover gasToCharge := 3000 @@ -3499,8 +3501,7 @@ object "EvmEmulator" { isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } - function isConstructedEvmContract(addr) -> isConstructedEVM { - let rawCodeHash := getRawCodeHash(addr) + function isHashOfConstructedEvmContract(rawCodeHash) -> isConstructedEVM { let version := shr(248, rawCodeHash) let isConstructedFlag := xor(shr(240, rawCodeHash), 1) isConstructedEVM := and(eq(version, 2), isConstructedFlag) @@ -3789,21 +3790,16 @@ object "EvmEmulator" { //////////////////////////////////////////////////////////////// function performCall(oldSp, evmGasLeft, oldStackHead, isStatic) -> newGasLeft, sp, stackHead { - let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize + let gasToPass, rawAddr, value, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 7) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawAddr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) - addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - - checkMemIsAccessible(argsOffset, argsSize) - checkMemIsAccessible(retOffset, retSize) - // 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). @@ -3811,13 +3807,7 @@ object "EvmEmulator" { // 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. // 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. - let gasUsed := 100 // warm address access cost - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 // cold address access cost - } - - // memory_expansion_cost - gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) + let addr, gasUsed := _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) if gt(value, 0) { if isStatic { @@ -3855,27 +3845,16 @@ object "EvmEmulator" { } function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { - let gasToPass,addr, argsOffset, argsSize, retOffset, retSize + let gasToPass, rawAddr, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawAddr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) - addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - - checkMemIsAccessible(argsOffset, argsSize) - checkMemIsAccessible(retOffset, retSize) - - let gasUsed := 100 // warm address access cost - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 // cold address access cost - } - - // memory_expansion_cost - gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) + let addr, gasUsed := _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) evmGasLeft := chargeGas(evmGasLeft, gasUsed) gasToPass := capGasForCall(evmGasLeft, gasToPass) @@ -3898,62 +3877,88 @@ object "EvmEmulator" { function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGasLeft, sp, stackHead { - let addr, gasToPass, argsOffset, argsSize, retOffset, retSize + let gasToPass, rawAddr, rawArgsOffset, argsSize, rawRetOffset, retSize popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawAddr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawArgsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) + rawRetOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) - addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + let addr, gasUsed := _genericPrecallLogic(rawAddr, rawArgsOffset, argsSize, rawRetOffset, retSize) - checkMemIsAccessible(argsOffset, argsSize) - checkMemIsAccessible(retOffset, retSize) + newGasLeft := chargeGas(evmGasLeft, gasUsed) + gasToPass := capGasForCall(newGasLeft, gasToPass) - let gasUsed := 100 // warm address access cost - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 // cold address access cost - } + newGasLeft := sub(newGasLeft, gasToPass) - // memory_expansion_cost - gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) + let success + let frameGasLeft := gasToPass - evmGasLeft := chargeGas(evmGasLeft, gasUsed) + let retOffset := add(MEM_OFFSET(), rawRetOffset) + let argsOffset := add(MEM_OFFSET(), rawArgsOffset) - // it is also not possible to delegatecall precompiles - if iszero(isEvmContract(addr)) { - revertWithGas(evmGasLeft) + let rawCodeHash := getRawCodeHash(addr) + switch isHashOfConstructedEvmContract(rawCodeHash) + case 0 { + // Not a constructed EVM contract + let precompileCost := getGasForPrecompiles(addr, argsSize) + switch precompileCost + case 0 { + // Not a precompile + switch eq(1, shr(248, rawCodeHash)) + case 0 { + // Empty contract or EVM contract being constructed + success := delegatecall(gas(), addr, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + } + default { + // We forbid delegatecalls to EraVM native contracts + _eraseReturndataPointer() + } + } + default { + // Precompile. Simlate using staticcall, since EraVM behavior differs here + success, frameGasLeft := callPrecompile(addr, precompileCost, gasToPass, 0, argsOffset, argsSize, retOffset, retSize, true) + } } + default { + // Constructed EVM contract + pushEvmFrame(gasToPass, isStatic) + // pass all remaining native gas + success := delegatecall(gas(), addr, argsOffset, argsSize, 0, 0) - gasToPass := capGasForCall(evmGasLeft, gasToPass) - evmGasLeft := sub(evmGasLeft, gasToPass) + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + if iszero(success) { + resetEvmFrame() + } + } - pushEvmFrame(gasToPass, isStatic) - let success := delegatecall( - gas(), // pass all remaining native gas - addr, - add(MEM_OFFSET(), argsOffset), - argsSize, - 0, - 0 - ) + newGasLeft := add(newGasLeft, frameGasLeft) + stackHead := success + } - let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET(), retOffset), retSize) - if iszero(success) { - resetEvmFrame() + function _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) -> addr, gasUsed { + addr := and(rawAddr, 0xffffffffffffffffffffffffffffffffffffffff) + + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) + + gasUsed := 100 // warm address access cost + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + gasUsed := 2600 // cold address access cost } - newGasLeft := add(evmGasLeft, frameGasLeft) - stackHead := success + // memory_expansion_cost + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) } function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - switch isConstructedEvmContract(addr) + switch isHashOfConstructedEvmContract(getRawCodeHash(addr)) case 0 { // zkEVM native call - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + let precompileCost := getGasForPrecompiles(addr, argsSize) switch precompileCost case 0 { // just smart contract @@ -4046,8 +4051,7 @@ object "EvmEmulator" { // 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() when passing the argsOffset - function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { + function getGasForPrecompiles(addr, argsSize) -> gasToCharge { switch addr case 0x01 { // ecRecover gasToCharge := 3000 diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index bb0c602db..adc931e45 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -336,8 +336,7 @@ function isEvmContract(addr) -> isEVM { isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36) } -function isConstructedEvmContract(addr) -> isConstructedEVM { - let rawCodeHash := getRawCodeHash(addr) +function isHashOfConstructedEvmContract(rawCodeHash) -> isConstructedEVM { let version := shr(248, rawCodeHash) let isConstructedFlag := xor(shr(240, rawCodeHash), 1) isConstructedEVM := and(eq(version, 2), isConstructedFlag) @@ -626,21 +625,16 @@ function resetEvmFrame() { //////////////////////////////////////////////////////////////// function performCall(oldSp, evmGasLeft, oldStackHead, isStatic) -> newGasLeft, sp, stackHead { - let gasToPass, addr, value, argsOffset, argsSize, retOffset, retSize + let gasToPass, rawAddr, value, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 7) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawAddr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) value, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) - addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - - checkMemIsAccessible(argsOffset, argsSize) - checkMemIsAccessible(retOffset, retSize) - // 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). @@ -648,13 +642,7 @@ function performCall(oldSp, evmGasLeft, oldStackHead, isStatic) -> newGasLeft, s // 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. // 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. - let gasUsed := 100 // warm address access cost - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 // cold address access cost - } - - // memory_expansion_cost - gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) + let addr, gasUsed := _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) if gt(value, 0) { if isStatic { @@ -692,27 +680,16 @@ function performCall(oldSp, evmGasLeft, oldStackHead, isStatic) -> newGasLeft, s } function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, stackHead { - let gasToPass,addr, argsOffset, argsSize, retOffset, retSize + let gasToPass, rawAddr, argsOffset, argsSize, retOffset, retSize popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawAddr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) - addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) - - checkMemIsAccessible(argsOffset, argsSize) - checkMemIsAccessible(retOffset, retSize) - - let gasUsed := 100 // warm address access cost - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 // cold address access cost - } - - // memory_expansion_cost - gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) + let addr, gasUsed := _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) evmGasLeft := chargeGas(evmGasLeft, gasUsed) gasToPass := capGasForCall(evmGasLeft, gasToPass) @@ -735,62 +712,88 @@ function performStaticCall(oldSp, evmGasLeft, oldStackHead) -> newGasLeft, sp, s function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGasLeft, sp, stackHead { - let addr, gasToPass, argsOffset, argsSize, retOffset, retSize + let gasToPass, rawAddr, rawArgsOffset, argsSize, rawRetOffset, retSize popStackCheck(oldSp, 6) gasToPass, sp, stackHead := popStackItemWithoutCheck(oldSp, oldStackHead) - addr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - argsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawAddr, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) + rawArgsOffset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) argsSize, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - retOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) + rawRetOffset, sp, retSize := popStackItemWithoutCheck(sp, stackHead) - addr := and(addr, 0xffffffffffffffffffffffffffffffffffffffff) + let addr, gasUsed := _genericPrecallLogic(rawAddr, rawArgsOffset, argsSize, rawRetOffset, retSize) - checkMemIsAccessible(argsOffset, argsSize) - checkMemIsAccessible(retOffset, retSize) + newGasLeft := chargeGas(evmGasLeft, gasUsed) + gasToPass := capGasForCall(newGasLeft, gasToPass) - let gasUsed := 100 // warm address access cost - if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { - gasUsed := 2600 // cold address access cost - } + newGasLeft := sub(newGasLeft, gasToPass) - // memory_expansion_cost - gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) + let success + let frameGasLeft := gasToPass - evmGasLeft := chargeGas(evmGasLeft, gasUsed) + let retOffset := add(MEM_OFFSET(), rawRetOffset) + let argsOffset := add(MEM_OFFSET(), rawArgsOffset) - // it is also not possible to delegatecall precompiles - if iszero(isEvmContract(addr)) { - revertWithGas(evmGasLeft) + let rawCodeHash := getRawCodeHash(addr) + switch isHashOfConstructedEvmContract(rawCodeHash) + case 0 { + // Not a constructed EVM contract + let precompileCost := getGasForPrecompiles(addr, argsSize) + switch precompileCost + case 0 { + // Not a precompile + switch eq(1, shr(248, rawCodeHash)) + case 0 { + // Empty contract or EVM contract being constructed + success := delegatecall(gas(), addr, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() + } + default { + // We forbid delegatecalls to EraVM native contracts + _eraseReturndataPointer() + } + } + default { + // Precompile. Simlate using staticcall, since EraVM behavior differs here + success, frameGasLeft := callPrecompile(addr, precompileCost, gasToPass, 0, argsOffset, argsSize, retOffset, retSize, true) + } + } + default { + // Constructed EVM contract + pushEvmFrame(gasToPass, isStatic) + // pass all remaining native gas + success := delegatecall(gas(), addr, argsOffset, argsSize, 0, 0) + + frameGasLeft := _saveReturndataAfterEVMCall(retOffset, retSize) + if iszero(success) { + resetEvmFrame() + } } - gasToPass := capGasForCall(evmGasLeft, gasToPass) - evmGasLeft := sub(evmGasLeft, gasToPass) + newGasLeft := add(newGasLeft, frameGasLeft) + stackHead := success +} - pushEvmFrame(gasToPass, isStatic) - let success := delegatecall( - gas(), // pass all remaining native gas - addr, - add(MEM_OFFSET(), argsOffset), - argsSize, - 0, - 0 - ) +function _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) -> addr, gasUsed { + addr := and(rawAddr, 0xffffffffffffffffffffffffffffffffffffffff) - let frameGasLeft := _saveReturndataAfterEVMCall(add(MEM_OFFSET(), retOffset), retSize) - if iszero(success) { - resetEvmFrame() + checkMemIsAccessible(argsOffset, argsSize) + checkMemIsAccessible(retOffset, retSize) + + gasUsed := 100 // warm address access cost + if iszero($llvm_AlwaysInline_llvm$_warmAddress(addr)) { + gasUsed := 2600 // cold address access cost } - newGasLeft := add(evmGasLeft, frameGasLeft) - stackHead := success + // memory_expansion_cost + gasUsed := add(gasUsed, expandMemory2(retOffset, retSize, argsOffset, argsSize)) } function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - switch isConstructedEvmContract(addr) + switch isHashOfConstructedEvmContract(getRawCodeHash(addr)) case 0 { // zkEVM native call - let precompileCost := getGasForPrecompiles(addr, argsOffset, argsSize) + let precompileCost := getGasForPrecompiles(addr, argsSize) switch precompileCost case 0 { // just smart contract @@ -883,8 +886,7 @@ function capGasForCall(evmGasLeft, oldGasToPass) -> gasToPass { // 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() when passing the argsOffset -function getGasForPrecompiles(addr, argsOffset, argsSize) -> gasToCharge { +function getGasForPrecompiles(addr, argsSize) -> gasToCharge { switch addr case 0x01 { // ecRecover gasToCharge := 3000 From 483b099be582127df0b1291ab8b75d192b1db824 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 5 Dec 2024 21:06:13 +0100 Subject: [PATCH 170/183] fix(EVM): Handle corner case of KECCAK with 0 size (#1121) --- system-contracts/contracts/EvmEmulator.yul | 32 +++++++++++++------ .../evm-emulator/EvmEmulatorLoop.template.yul | 16 +++++++--- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index c62b333da..dabf78485 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1529,21 +1529,27 @@ object "EvmEmulator" { case 0x20 { // OP_KECCAK256 evmGasLeft := chargeGas(evmGasLeft, 30) - let offset, size + let rawOffset, size popStackCheck(sp, 2) - offset, sp, size := popStackItemWithoutCheck(sp, stackHead) + rawOffset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(offset, size) + checkMemIsAccessible(rawOffset, 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(offset, size)) + let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(rawOffset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - stackHead := keccak256(add(MEM_OFFSET(), offset), size) + let offset + if size { + // use 0 as offset if size is 0 + offset := add(MEM_OFFSET(), rawOffset) + } + + stackHead := keccak256(offset, size) ip := add(ip, 1) } @@ -4632,21 +4638,27 @@ object "EvmEmulator" { case 0x20 { // OP_KECCAK256 evmGasLeft := chargeGas(evmGasLeft, 30) - let offset, size + let rawOffset, size popStackCheck(sp, 2) - offset, sp, size := popStackItemWithoutCheck(sp, stackHead) + rawOffset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(offset, size) + checkMemIsAccessible(rawOffset, 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(offset, size)) + let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(rawOffset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - stackHead := keccak256(add(MEM_OFFSET(), offset), size) + let offset + if size { + // use 0 as offset if size is 0 + offset := add(MEM_OFFSET(), rawOffset) + } + + stackHead := keccak256(offset, size) ip := add(ip, 1) } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 20cdc0a2f..fde5817f5 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -278,21 +278,27 @@ for { } true { } { case 0x20 { // OP_KECCAK256 evmGasLeft := chargeGas(evmGasLeft, 30) - let offset, size + let rawOffset, size popStackCheck(sp, 2) - offset, sp, size := popStackItemWithoutCheck(sp, stackHead) + rawOffset, sp, size := popStackItemWithoutCheck(sp, stackHead) - checkMemIsAccessible(offset, size) + checkMemIsAccessible(rawOffset, 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(offset, size)) + let dynamicGas := add(mul(6, shr(5, add(size, 31))), expandMemory(rawOffset, size)) evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - stackHead := keccak256(add(MEM_OFFSET(), offset), size) + let offset + if size { + // use 0 as offset if size is 0 + offset := add(MEM_OFFSET(), rawOffset) + } + + stackHead := keccak256(offset, size) ip := add(ip, 1) } From d61e38dd6d7be655b7f43f08985158391d6d0d17 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 6 Dec 2024 11:59:23 +0100 Subject: [PATCH 171/183] fix(EVM): Make fetchDeployedCode more robust (2) (#1123) --- system-contracts/contracts/EvmEmulator.yul | 114 +++++++++--------- .../EvmEmulatorFunctions.template.yul | 50 ++++---- .../evm-emulator/EvmEmulatorLoop.template.yul | 7 +- 3 files changed, 90 insertions(+), 81 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index dabf78485..4da1e794f 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -408,29 +408,35 @@ object "EvmEmulator" { function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) mstore(0, codeHash) - // The first word of returndata is the true length of the bytecode - let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) - - if gt(len, codeLen) { - len := codeLen - } - - let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length - - let _returndatasize := returndatasize() - if gt(shiftedSrcOffset, _returndatasize) { - shiftedSrcOffset := _returndatasize - } - - if gt(add(len, shiftedSrcOffset), _returndatasize) { - len := sub(_returndatasize, shiftedSrcOffset) - } - - if len { - returndatacopy(dstOffset, shiftedSrcOffset, len) - } + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + // it fails if we don't have any code deployed at this address + if success { + returndatacopy(0, 0, 32) + // The first word of returndata is the true length of the bytecode + let codeLen := mload(0) - copiedLen := len + if gt(len, codeLen) { + len := codeLen + } + + let shiftedSrcOffset := add(32, srcOffset) // first 32 bytes is length + + let _returndatasize := returndatasize() + if gt(shiftedSrcOffset, _returndatasize) { + shiftedSrcOffset := _returndatasize + } + + if gt(add(len, shiftedSrcOffset), _returndatasize) { + len := sub(_returndatasize, shiftedSrcOffset) + } + + if len { + returndatacopy(dstOffset, shiftedSrcOffset, len) + } + + copiedLen := len + } } // Returns the length of the EVM bytecode. @@ -1759,11 +1765,8 @@ object "EvmEmulator" { } if gt(len, 0) { - let copiedLen - if getRawCodeHash(addr) { - // Gets the code from the addr - copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) - } + // Gets the code from the addr + let copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) if lt(copiedLen, len) { $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, copiedLen), sub(len, copiedLen)) @@ -3517,29 +3520,35 @@ object "EvmEmulator" { function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) mstore(0, codeHash) - // The first word of returndata is the true length of the bytecode - let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) - - if gt(len, codeLen) { - len := codeLen - } - - let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length - - let _returndatasize := returndatasize() - if gt(shiftedSrcOffset, _returndatasize) { - shiftedSrcOffset := _returndatasize - } - - if gt(add(len, shiftedSrcOffset), _returndatasize) { - len := sub(_returndatasize, shiftedSrcOffset) - } - - if len { - returndatacopy(dstOffset, shiftedSrcOffset, len) - } + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + // it fails if we don't have any code deployed at this address + if success { + returndatacopy(0, 0, 32) + // The first word of returndata is the true length of the bytecode + let codeLen := mload(0) - copiedLen := len + if gt(len, codeLen) { + len := codeLen + } + + let shiftedSrcOffset := add(32, srcOffset) // first 32 bytes is length + + let _returndatasize := returndatasize() + if gt(shiftedSrcOffset, _returndatasize) { + shiftedSrcOffset := _returndatasize + } + + if gt(add(len, shiftedSrcOffset), _returndatasize) { + len := sub(_returndatasize, shiftedSrcOffset) + } + + if len { + returndatacopy(dstOffset, shiftedSrcOffset, len) + } + + copiedLen := len + } } // Returns the length of the EVM bytecode. @@ -4868,11 +4877,8 @@ object "EvmEmulator" { } if gt(len, 0) { - let copiedLen - if getRawCodeHash(addr) { - // Gets the code from the addr - copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) - } + // Gets the code from the addr + let copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) if lt(copiedLen, len) { $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, copiedLen), sub(len, copiedLen)) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index adc931e45..011f7b13a 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -346,29 +346,35 @@ function isHashOfConstructedEvmContract(rawCodeHash) -> isConstructedEVM { function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { let codeHash := getRawCodeHash(addr) mstore(0, codeHash) - // The first word of returndata is the true length of the bytecode - let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32) - - if gt(len, codeLen) { - len := codeLen - } - - let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length - - let _returndatasize := returndatasize() - if gt(shiftedSrcOffset, _returndatasize) { - shiftedSrcOffset := _returndatasize - } - - if gt(add(len, shiftedSrcOffset), _returndatasize) { - len := sub(_returndatasize, shiftedSrcOffset) - } - - if len { - returndatacopy(dstOffset, shiftedSrcOffset, len) - } + + let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) + // it fails if we don't have any code deployed at this address + if success { + returndatacopy(0, 0, 32) + // The first word of returndata is the true length of the bytecode + let codeLen := mload(0) - copiedLen := len + if gt(len, codeLen) { + len := codeLen + } + + let shiftedSrcOffset := add(32, srcOffset) // first 32 bytes is length + + let _returndatasize := returndatasize() + if gt(shiftedSrcOffset, _returndatasize) { + shiftedSrcOffset := _returndatasize + } + + if gt(add(len, shiftedSrcOffset), _returndatasize) { + len := sub(_returndatasize, shiftedSrcOffset) + } + + if len { + returndatacopy(dstOffset, shiftedSrcOffset, len) + } + + copiedLen := len + } } // Returns the length of the EVM bytecode. diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index fde5817f5..c76854588 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -508,11 +508,8 @@ for { } true { } { } if gt(len, 0) { - let copiedLen - if getRawCodeHash(addr) { - // Gets the code from the addr - copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) - } + // Gets the code from the addr + let copiedLen := fetchDeployedCode(addr, dstOffset, srcOffset, len) if lt(copiedLen, len) { $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, copiedLen), sub(len, copiedLen)) From 47b2ddd983e7b398a784a1ed542c2426d0d3e297 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 6 Dec 2024 12:39:15 +0100 Subject: [PATCH 172/183] fix(EVM): Increase max allowed memory (2) (#1124) --- system-contracts/contracts/EvmEmulator.yul | 8 ++++---- .../evm-emulator/EvmEmulatorFunctions.template.yul | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 4da1e794f..625231950 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -166,9 +166,9 @@ object "EvmEmulator" { } // Used to simplify gas calculations for memory expansion. - // The cost to increase the memory to 4 MB is close to 30M gas + // The cost to increase the memory to 12 MB is close to 277M EVM gas function MAX_POSSIBLE_MEM_LEN() -> max { - max := 0x400000 // 4MB + max := 0xC00000 // 12MB } function MAX_UINT() -> max_uint { @@ -3278,9 +3278,9 @@ object "EvmEmulator" { } // Used to simplify gas calculations for memory expansion. - // The cost to increase the memory to 4 MB is close to 30M gas + // The cost to increase the memory to 12 MB is close to 277M EVM gas function MAX_POSSIBLE_MEM_LEN() -> max { - max := 0x400000 // 4MB + max := 0xC00000 // 12MB } function MAX_UINT() -> max_uint { diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 011f7b13a..04ce45ea8 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -104,9 +104,9 @@ function MEM_OFFSET() -> offset { } // Used to simplify gas calculations for memory expansion. -// The cost to increase the memory to 4 MB is close to 30M gas +// The cost to increase the memory to 12 MB is close to 277M EVM gas function MAX_POSSIBLE_MEM_LEN() -> max { - max := 0x400000 // 4MB + max := 0xC00000 // 12MB } function MAX_UINT() -> max_uint { From c4c964b5704ac667f099da7361abf70cbb654689 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 6 Dec 2024 15:07:56 +0100 Subject: [PATCH 173/183] fix(EVM): Implement EXTCODEHASH in emulator (#1125) --- system-contracts/contracts/EvmEmulator.yul | 80 +++++++++++++++---- .../EvmEmulatorFunctions.template.yul | 5 ++ .../evm-emulator/EvmEmulatorLoop.template.yul | 35 ++++++-- 3 files changed, 96 insertions(+), 24 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 625231950..927c5fdd4 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -191,6 +191,11 @@ object "EvmEmulator" { function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 + function EMPTY_KECCAK() -> value { // keccak("") + value := 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 + } + + //////////////////////////////////////////////////////////////// // GENERAL FUNCTIONS //////////////////////////////////////////////////////////////// @@ -1818,20 +1823,39 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - ip := add(ip, 1) - if iszero(addr) { - stackHead := 0 - continue - } - - switch isEvmContract(addr) + let rawCodeHash := getRawCodeHash(addr) + switch isHashOfConstructedEvmContract(rawCodeHash) case 0 { - stackHead := extcodehash(addr) + let codeLen := and(shr(224, rawCodeHash), 0xffff) + + if codeLen { + if lt(addr, 0x100) { + // precompiles and 0x00 + codeLen := 0 + } + } + + switch codeLen + case 0 { + stackHead := EMPTY_KECCAK() + + if iszero(getRawNonce(addr)) { + if iszero(balance(addr)) { + stackHead := 0 + } + } + } + default { + // zkVM contract + stackHead := rawCodeHash + } } default { + // Get precalculated keccak of EVM code stackHead := getEvmExtcodehash(addr) } + ip := add(ip, 1) } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) @@ -3303,6 +3327,11 @@ object "EvmEmulator" { function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 + function EMPTY_KECCAK() -> value { // keccak("") + value := 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 + } + + //////////////////////////////////////////////////////////////// // GENERAL FUNCTIONS //////////////////////////////////////////////////////////////// @@ -4930,20 +4959,39 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - ip := add(ip, 1) - if iszero(addr) { - stackHead := 0 - continue - } - - switch isEvmContract(addr) + let rawCodeHash := getRawCodeHash(addr) + switch isHashOfConstructedEvmContract(rawCodeHash) case 0 { - stackHead := extcodehash(addr) + let codeLen := and(shr(224, rawCodeHash), 0xffff) + + if codeLen { + if lt(addr, 0x100) { + // precompiles and 0x00 + codeLen := 0 + } + } + + switch codeLen + case 0 { + stackHead := EMPTY_KECCAK() + + if iszero(getRawNonce(addr)) { + if iszero(balance(addr)) { + stackHead := 0 + } + } + } + default { + // zkVM contract + stackHead := rawCodeHash + } } default { + // Get precalculated keccak of EVM code stackHead := getEvmExtcodehash(addr) } + ip := add(ip, 1) } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 04ce45ea8..627a9162f 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -129,6 +129,11 @@ function OVERHEAD() -> overhead { overhead := 2000 } function UINT32_MAX() -> ret { ret := 4294967295 } // 2^32 - 1 +function EMPTY_KECCAK() -> value { // keccak("") + value := 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 +} + + //////////////////////////////////////////////////////////////// // GENERAL FUNCTIONS //////////////////////////////////////////////////////////////// diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index c76854588..e1eeae682 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -561,20 +561,39 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 2500) } - ip := add(ip, 1) - if iszero(addr) { - stackHead := 0 - continue - } - - switch isEvmContract(addr) + let rawCodeHash := getRawCodeHash(addr) + switch isHashOfConstructedEvmContract(rawCodeHash) case 0 { - stackHead := extcodehash(addr) + let codeLen := and(shr(224, rawCodeHash), 0xffff) + + if codeLen { + if lt(addr, 0x100) { + // precompiles and 0x00 + codeLen := 0 + } + } + + switch codeLen + case 0 { + stackHead := EMPTY_KECCAK() + + if iszero(getRawNonce(addr)) { + if iszero(balance(addr)) { + stackHead := 0 + } + } + } + default { + // zkVM contract + stackHead := rawCodeHash + } } default { + // Get precalculated keccak of EVM code stackHead := getEvmExtcodehash(addr) } + ip := add(ip, 1) } case 0x40 { // OP_BLOCKHASH evmGasLeft := chargeGas(evmGasLeft, 20) From 921b3e37de45beacabc517f2f4e2fec5416888fb Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 6 Dec 2024 18:39:35 +0100 Subject: [PATCH 174/183] fix(EVM): Add stipends for calls to zkVM contracts (#1126) --- system-contracts/contracts/EvmEmulator.yul | 64 ++++++++++++++++--- .../EvmEmulatorFunctions.template.yul | 32 ++++++++-- 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 927c5fdd4..f1a37ca8d 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -863,14 +863,15 @@ object "EvmEmulator" { } function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - switch isHashOfConstructedEvmContract(getRawCodeHash(addr)) + let rawCodeHash := getRawCodeHash(addr) + switch isHashOfConstructedEvmContract(rawCodeHash) case 0 { // zkEVM native call let precompileCost := getGasForPrecompiles(addr, argsSize) switch precompileCost case 0 { // just smart contract - success, frameGasLeft := callZkVmNative(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) + success, frameGasLeft := callZkVmNative(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic, rawCodeHash) } default { // precompile @@ -919,9 +920,20 @@ object "EvmEmulator" { } // Call native ZkVm contract from EVM context - function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { + function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic, rawCodeHash) -> success, frameGasLeft { let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas + let additionalStipend + if iszero(and(shr(224, rawCodeHash), 0xffff)) { // if codelen is zero + additionalStipend := 6000 // should cover first access to empty account + } + + if value { + additionalStipend := 27000 // Stipend for MsgValueSimulator. Covered by positive_value_cost + } + + zkEvmGasToPass := add(zkEvmGasToPass, additionalStipend) + if gt(zkEvmGasToPass, UINT32_MAX()) { // just in case zkEvmGasToPass := UINT32_MAX() } @@ -937,11 +949,21 @@ object "EvmEmulator" { let zkEvmGasUsed := sub(zkEvmGasBefore, gas()) _saveReturndataAfterZkEVMCall() - + if gt(zkEvmGasUsed, zkEvmGasBefore) { // overflow case - zkEvmGasUsed := zkEvmGasToPass // should never happen + zkEvmGasUsed := 0 // should never happen + } + + switch gt(zkEvmGasUsed, additionalStipend) + case 0 { + zkEvmGasUsed := 0 + } + default { + zkEvmGasUsed := sub(zkEvmGasUsed, additionalStipend) } + zkEvmGasToPass := sub(zkEvmGasToPass, additionalStipend) + // refund gas if gt(zkEvmGasToPass, zkEvmGasUsed) { frameGasLeft := div(sub(zkEvmGasToPass, zkEvmGasUsed), GAS_DIVISOR()) @@ -3999,14 +4021,15 @@ object "EvmEmulator" { } function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - switch isHashOfConstructedEvmContract(getRawCodeHash(addr)) + let rawCodeHash := getRawCodeHash(addr) + switch isHashOfConstructedEvmContract(rawCodeHash) case 0 { // zkEVM native call let precompileCost := getGasForPrecompiles(addr, argsSize) switch precompileCost case 0 { // just smart contract - success, frameGasLeft := callZkVmNative(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) + success, frameGasLeft := callZkVmNative(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic, rawCodeHash) } default { // precompile @@ -4055,9 +4078,20 @@ object "EvmEmulator" { } // Call native ZkVm contract from EVM context - function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { + function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic, rawCodeHash) -> success, frameGasLeft { let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas + let additionalStipend + if iszero(and(shr(224, rawCodeHash), 0xffff)) { // if codelen is zero + additionalStipend := 6000 // should cover first access to empty account + } + + if value { + additionalStipend := 27000 // Stipend for MsgValueSimulator. Covered by positive_value_cost + } + + zkEvmGasToPass := add(zkEvmGasToPass, additionalStipend) + if gt(zkEvmGasToPass, UINT32_MAX()) { // just in case zkEvmGasToPass := UINT32_MAX() } @@ -4073,11 +4107,21 @@ object "EvmEmulator" { let zkEvmGasUsed := sub(zkEvmGasBefore, gas()) _saveReturndataAfterZkEVMCall() - + if gt(zkEvmGasUsed, zkEvmGasBefore) { // overflow case - zkEvmGasUsed := zkEvmGasToPass // should never happen + zkEvmGasUsed := 0 // should never happen + } + + switch gt(zkEvmGasUsed, additionalStipend) + case 0 { + zkEvmGasUsed := 0 + } + default { + zkEvmGasUsed := sub(zkEvmGasUsed, additionalStipend) } + zkEvmGasToPass := sub(zkEvmGasToPass, additionalStipend) + // refund gas if gt(zkEvmGasToPass, zkEvmGasUsed) { frameGasLeft := div(sub(zkEvmGasToPass, zkEvmGasUsed), GAS_DIVISOR()) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 627a9162f..eb24341b3 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -801,14 +801,15 @@ function _genericPrecallLogic(rawAddr, argsOffset, argsSize, retOffset, retSize) } function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - switch isHashOfConstructedEvmContract(getRawCodeHash(addr)) + let rawCodeHash := getRawCodeHash(addr) + switch isHashOfConstructedEvmContract(rawCodeHash) case 0 { // zkEVM native call let precompileCost := getGasForPrecompiles(addr, argsSize) switch precompileCost case 0 { // just smart contract - success, frameGasLeft := callZkVmNative(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) + success, frameGasLeft := callZkVmNative(addr, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic, rawCodeHash) } default { // precompile @@ -857,9 +858,20 @@ function callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, args } // Call native ZkVm contract from EVM context -function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { +function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic, rawCodeHash) -> success, frameGasLeft { let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas + let additionalStipend + if iszero(and(shr(224, rawCodeHash), 0xffff)) { // if codelen is zero + additionalStipend := 6000 // should cover first access to empty account + } + + if value { + additionalStipend := 27000 // Stipend for MsgValueSimulator. Covered by positive_value_cost + } + + zkEvmGasToPass := add(zkEvmGasToPass, additionalStipend) + if gt(zkEvmGasToPass, UINT32_MAX()) { // just in case zkEvmGasToPass := UINT32_MAX() } @@ -875,11 +887,21 @@ function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffs let zkEvmGasUsed := sub(zkEvmGasBefore, gas()) _saveReturndataAfterZkEVMCall() - + if gt(zkEvmGasUsed, zkEvmGasBefore) { // overflow case - zkEvmGasUsed := zkEvmGasToPass // should never happen + zkEvmGasUsed := 0 // should never happen + } + + switch gt(zkEvmGasUsed, additionalStipend) + case 0 { + zkEvmGasUsed := 0 + } + default { + zkEvmGasUsed := sub(zkEvmGasUsed, additionalStipend) } + zkEvmGasToPass := sub(zkEvmGasToPass, additionalStipend) + // refund gas if gt(zkEvmGasToPass, zkEvmGasUsed) { frameGasLeft := div(sub(zkEvmGasToPass, zkEvmGasUsed), GAS_DIVISOR()) From ef8012290f0b04665edd002116e5443d33c0f247 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 6 Dec 2024 19:22:18 +0100 Subject: [PATCH 175/183] fix(EVM): Make CREATE flow equivalent to EVM (#1127) --- .../contracts/ContractDeployer.sol | 9 +- system-contracts/contracts/EvmEmulator.yul | 86 +++++++++++++------ .../EvmEmulatorFunctions.template.yul | 43 +++++++--- 3 files changed, 94 insertions(+), 44 deletions(-) diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 7032bacad..3b36ed732 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -238,13 +238,6 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { newAddress = Utils.getNewAddressCreateEVM(msg.sender, senderNonce); } - // Unfortunately we can not provide revert reason as it would break EVM compatibility - // we should not increase nonce in case of collision - // solhint-disable-next-line reason-string, gas-custom-errors - require(NONCE_HOLDER_SYSTEM_CONTRACT.getRawNonce(newAddress) == 0x0); - // solhint-disable-next-line reason-string, gas-custom-errors - require(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.getCodeHash(uint256(uint160(newAddress))) == 0x0); - return newAddress; } @@ -257,7 +250,7 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address _newAddress, bytes calldata _initCode ) external payable onlySystemCallFromEvmEmulator returns (uint256, address) { - uint256 constructorReturnEvmGas = _evmDeployOnAddress(msg.sender, _newAddress, _initCode); + uint256 constructorReturnEvmGas = _performDeployOnAddressEVM(msg.sender, _newAddress, AccountAbstractionVersion.None, _initCode); return (constructorReturnEvmGas, _newAddress); } diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index f1a37ca8d..c913a49ad 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1134,9 +1134,15 @@ object "EvmEmulator" { function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { let gasForTheCall := capGasForCall(evmGasLeftOld, evmGasLeftOld) // pass 63/64 of remaining gas - let bytecodeHash := 0 + let bytecodeHash if isCreate2 { - bytecodeHash := keccak256(offset, size) + switch size + case 0 { + bytecodeHash := EMPTY_KECCAK() + } + default { + bytecodeHash := keccak256(offset, size) + } } // we want to calculate the address of new contract, and if it is deployable (no collision), @@ -1146,22 +1152,35 @@ object "EvmEmulator" { mstore(0, 0xf81dae8600000000000000000000000000000000000000000000000000000000) mstore(4, salt) mstore(36, bytecodeHash) - let precreateResult := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) - - if iszero(precreateResult) { - // Collision, nonce overflow or EVM not allowed. - // This is *internal* panic, consuming all passed gas. - // Note: we should not consume all gas if nonce overflowed, but this should not happen in reality anyway - evmGasLeft := chargeGas(evmGasLeftOld, gasForTheCall) - } + let canBeDeployed := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) - if precreateResult { + if canBeDeployed { returndatacopy(0, 0, 32) addr := mload(0) pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) // will stay warm even if constructor reverts // so even if constructor reverts, nonce stays incremented and addr stays warm - + + // check for code collision + canBeDeployed := 0 + if iszero(getRawCodeHash(addr)) { + // check for nonce collision + if iszero(getRawNonce(addr)) { + canBeDeployed := 1 + } + } + } + + if iszero(canBeDeployed) { + // Nonce overflow, EVM not allowed or collision. + // This is *internal* panic, consuming all passed gas. + // Note: we should not consume all gas if nonce overflowed, but this should not happen in reality anyway + evmGasLeft := chargeGas(evmGasLeftOld, gasForTheCall) + addr := 0 + } + + + if canBeDeployed { // verification of the correctness of the deployed bytecode and payment of gas for its storage will occur in the frame of the new contract pushEvmFrame(gasForTheCall, false) @@ -4292,9 +4311,15 @@ object "EvmEmulator" { function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { let gasForTheCall := capGasForCall(evmGasLeftOld, evmGasLeftOld) // pass 63/64 of remaining gas - let bytecodeHash := 0 + let bytecodeHash if isCreate2 { - bytecodeHash := keccak256(offset, size) + switch size + case 0 { + bytecodeHash := EMPTY_KECCAK() + } + default { + bytecodeHash := keccak256(offset, size) + } } // we want to calculate the address of new contract, and if it is deployable (no collision), @@ -4304,22 +4329,35 @@ object "EvmEmulator" { mstore(0, 0xf81dae8600000000000000000000000000000000000000000000000000000000) mstore(4, salt) mstore(36, bytecodeHash) - let precreateResult := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) - - if iszero(precreateResult) { - // Collision, nonce overflow or EVM not allowed. - // This is *internal* panic, consuming all passed gas. - // Note: we should not consume all gas if nonce overflowed, but this should not happen in reality anyway - evmGasLeft := chargeGas(evmGasLeftOld, gasForTheCall) - } + let canBeDeployed := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) - if precreateResult { + if canBeDeployed { returndatacopy(0, 0, 32) addr := mload(0) pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) // will stay warm even if constructor reverts // so even if constructor reverts, nonce stays incremented and addr stays warm - + + // check for code collision + canBeDeployed := 0 + if iszero(getRawCodeHash(addr)) { + // check for nonce collision + if iszero(getRawNonce(addr)) { + canBeDeployed := 1 + } + } + } + + if iszero(canBeDeployed) { + // Nonce overflow, EVM not allowed or collision. + // This is *internal* panic, consuming all passed gas. + // Note: we should not consume all gas if nonce overflowed, but this should not happen in reality anyway + evmGasLeft := chargeGas(evmGasLeftOld, gasForTheCall) + addr := 0 + } + + + if canBeDeployed { // verification of the correctness of the deployed bytecode and payment of gas for its storage will occur in the frame of the new contract pushEvmFrame(gasForTheCall, false) diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index eb24341b3..28edace55 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -1072,9 +1072,15 @@ function $llvm_NoInline_llvm$_genericCreate(offset, size, value, evmGasLeftOld, function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> evmGasLeft, addr { let gasForTheCall := capGasForCall(evmGasLeftOld, evmGasLeftOld) // pass 63/64 of remaining gas - let bytecodeHash := 0 + let bytecodeHash if isCreate2 { - bytecodeHash := keccak256(offset, size) + switch size + case 0 { + bytecodeHash := EMPTY_KECCAK() + } + default { + bytecodeHash := keccak256(offset, size) + } } // we want to calculate the address of new contract, and if it is deployable (no collision), @@ -1084,22 +1090,35 @@ function _executeCreate(offset, size, value, evmGasLeftOld, isCreate2, salt) -> mstore(0, 0xf81dae8600000000000000000000000000000000000000000000000000000000) mstore(4, salt) mstore(36, bytecodeHash) - let precreateResult := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) + let canBeDeployed := performSystemCallRevertable(DEPLOYER_SYSTEM_CONTRACT(), 68) - if iszero(precreateResult) { - // Collision, nonce overflow or EVM not allowed. - // This is *internal* panic, consuming all passed gas. - // Note: we should not consume all gas if nonce overflowed, but this should not happen in reality anyway - evmGasLeft := chargeGas(evmGasLeftOld, gasForTheCall) - } - - if precreateResult { + if canBeDeployed { returndatacopy(0, 0, 32) addr := mload(0) pop($llvm_AlwaysInline_llvm$_warmAddress(addr)) // will stay warm even if constructor reverts // so even if constructor reverts, nonce stays incremented and addr stays warm - + + // check for code collision + canBeDeployed := 0 + if iszero(getRawCodeHash(addr)) { + // check for nonce collision + if iszero(getRawNonce(addr)) { + canBeDeployed := 1 + } + } + } + + if iszero(canBeDeployed) { + // Nonce overflow, EVM not allowed or collision. + // This is *internal* panic, consuming all passed gas. + // Note: we should not consume all gas if nonce overflowed, but this should not happen in reality anyway + evmGasLeft := chargeGas(evmGasLeftOld, gasForTheCall) + addr := 0 + } + + + if canBeDeployed { // verification of the correctness of the deployed bytecode and payment of gas for its storage will occur in the frame of the new contract pushEvmFrame(gasForTheCall, false) From b61406b4f9925ddaa363dfab27fb7a0f69d8d8f5 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 8 Dec 2024 14:46:19 +0100 Subject: [PATCH 176/183] Handle Empty.sol as empty account --- system-contracts/contracts/EvmEmulator.yul | 66 +++++++++++-------- .../EvmEmulatorFunctions.template.yul | 33 ++++++---- 2 files changed, 60 insertions(+), 39 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index c913a49ad..cd45a53dd 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -815,16 +815,19 @@ object "EvmEmulator" { switch precompileCost case 0 { // Not a precompile - switch eq(1, shr(248, rawCodeHash)) - case 0 { - // Empty contract or EVM contract being constructed - success := delegatecall(gas(), addr, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() + _eraseReturndataPointer() + + let isCallToEmptyContract := iszero(addr) // 0x00 is always "empty" + if iszero(isCallToEmptyContract) { + isCallToEmptyContract := iszero(and(shr(224, rawCodeHash), 0xffff)) // is codelen zero? } - default { - // We forbid delegatecalls to EraVM native contracts - _eraseReturndataPointer() + + if isCallToEmptyContract { + success := delegatecall(gas(), addr, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() } + + // We forbid delegatecalls to EraVM native contracts } default { // Precompile. Simlate using staticcall, since EraVM behavior differs here @@ -923,12 +926,16 @@ object "EvmEmulator" { function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic, rawCodeHash) -> success, frameGasLeft { let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas - let additionalStipend - if iszero(and(shr(224, rawCodeHash), 0xffff)) { // if codelen is zero - additionalStipend := 6000 // should cover first access to empty account + let additionalStipend := 6000 // should cover first access to empty account + switch value + case 0 { + if gt(addr, 0) { // zero address is always "empty" + if and(shr(224, rawCodeHash), 0xffff) { // if codelen is not zero + additionalStipend := 0 + } + } } - - if value { + default { additionalStipend := 27000 // Stipend for MsgValueSimulator. Covered by positive_value_cost } @@ -3992,16 +3999,19 @@ object "EvmEmulator" { switch precompileCost case 0 { // Not a precompile - switch eq(1, shr(248, rawCodeHash)) - case 0 { - // Empty contract or EVM contract being constructed - success := delegatecall(gas(), addr, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() + _eraseReturndataPointer() + + let isCallToEmptyContract := iszero(addr) // 0x00 is always "empty" + if iszero(isCallToEmptyContract) { + isCallToEmptyContract := iszero(and(shr(224, rawCodeHash), 0xffff)) // is codelen zero? } - default { - // We forbid delegatecalls to EraVM native contracts - _eraseReturndataPointer() + + if isCallToEmptyContract { + success := delegatecall(gas(), addr, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() } + + // We forbid delegatecalls to EraVM native contracts } default { // Precompile. Simlate using staticcall, since EraVM behavior differs here @@ -4100,12 +4110,16 @@ object "EvmEmulator" { function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic, rawCodeHash) -> success, frameGasLeft { let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas - let additionalStipend - if iszero(and(shr(224, rawCodeHash), 0xffff)) { // if codelen is zero - additionalStipend := 6000 // should cover first access to empty account + let additionalStipend := 6000 // should cover first access to empty account + switch value + case 0 { + if gt(addr, 0) { // zero address is always "empty" + if and(shr(224, rawCodeHash), 0xffff) { // if codelen is not zero + additionalStipend := 0 + } + } } - - if value { + default { additionalStipend := 27000 // Stipend for MsgValueSimulator. Covered by positive_value_cost } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 28edace55..843e2ead3 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -753,16 +753,19 @@ function performDelegateCall(oldSp, evmGasLeft, isStatic, oldStackHead) -> newGa switch precompileCost case 0 { // Not a precompile - switch eq(1, shr(248, rawCodeHash)) - case 0 { - // Empty contract or EVM contract being constructed - success := delegatecall(gas(), addr, argsOffset, argsSize, retOffset, retSize) - _saveReturndataAfterZkEVMCall() + _eraseReturndataPointer() + + let isCallToEmptyContract := iszero(addr) // 0x00 is always "empty" + if iszero(isCallToEmptyContract) { + isCallToEmptyContract := iszero(and(shr(224, rawCodeHash), 0xffff)) // is codelen zero? } - default { - // We forbid delegatecalls to EraVM native contracts - _eraseReturndataPointer() + + if isCallToEmptyContract { + success := delegatecall(gas(), addr, argsOffset, argsSize, retOffset, retSize) + _saveReturndataAfterZkEVMCall() } + + // We forbid delegatecalls to EraVM native contracts } default { // Precompile. Simlate using staticcall, since EraVM behavior differs here @@ -861,12 +864,16 @@ function callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, args function callZkVmNative(addr, evmGasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic, rawCodeHash) -> success, frameGasLeft { let zkEvmGasToPass := mul(evmGasToPass, GAS_DIVISOR()) // convert EVM gas -> ZkVM gas - let additionalStipend - if iszero(and(shr(224, rawCodeHash), 0xffff)) { // if codelen is zero - additionalStipend := 6000 // should cover first access to empty account + let additionalStipend := 6000 // should cover first access to empty account + switch value + case 0 { + if gt(addr, 0) { // zero address is always "empty" + if and(shr(224, rawCodeHash), 0xffff) { // if codelen is not zero + additionalStipend := 0 + } + } } - - if value { + default { additionalStipend := 27000 // Stipend for MsgValueSimulator. Covered by positive_value_cost } From 72bbed03990d812e0c856266048b5d9f24769e43 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Sun, 8 Dec 2024 15:16:42 +0100 Subject: [PATCH 177/183] Do not call precompiles if not enough gas provided --- system-contracts/contracts/EvmEmulator.yul | 70 ++++++++++--------- .../EvmEmulatorFunctions.template.yul | 35 +++++----- 2 files changed, 57 insertions(+), 48 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index cd45a53dd..367aa87c9 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -900,26 +900,29 @@ object "EvmEmulator" { } function callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts - if lt(gasToPass, precompileCost) { - zkVmGasToPass := 0 // in EVM precompile should revert consuming all gas in that case - precompileCost := gasToPass // just in case - } - - switch isStatic + switch lt(gasToPass, precompileCost) case 0 { - success := rawCall(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts + + switch isStatic + case 0 { + success := rawCall(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + } + default { + success := rawStaticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) + } + + _saveReturndataAfterZkEVMCall() + + if success { + frameGasLeft := sub(gasToPass, precompileCost) + } + // else consume all provided gas } default { - success := rawStaticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) - } - - _saveReturndataAfterZkEVMCall() - - if success { - frameGasLeft := sub(gasToPass, precompileCost) + // consume all provided gas + _eraseReturndataPointer() } - // else consume all provided gas } // Call native ZkVm contract from EVM context @@ -4084,26 +4087,29 @@ object "EvmEmulator" { } function callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts - if lt(gasToPass, precompileCost) { - zkVmGasToPass := 0 // in EVM precompile should revert consuming all gas in that case - precompileCost := gasToPass // just in case - } - - switch isStatic + switch lt(gasToPass, precompileCost) case 0 { - success := rawCall(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts + + switch isStatic + case 0 { + success := rawCall(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + } + default { + success := rawStaticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) + } + + _saveReturndataAfterZkEVMCall() + + if success { + frameGasLeft := sub(gasToPass, precompileCost) + } + // else consume all provided gas } default { - success := rawStaticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) - } - - _saveReturndataAfterZkEVMCall() - - if success { - frameGasLeft := sub(gasToPass, precompileCost) + // consume all provided gas + _eraseReturndataPointer() } - // else consume all provided gas } // Call native ZkVm contract from EVM context diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 843e2ead3..00d579de5 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -838,26 +838,29 @@ function _genericCall(addr, gasToPass, value, argsOffset, argsSize, retOffset, r } function callPrecompile(addr, precompileCost, gasToPass, value, argsOffset, argsSize, retOffset, retSize, isStatic) -> success, frameGasLeft { - let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts - if lt(gasToPass, precompileCost) { - zkVmGasToPass := 0 // in EVM precompile should revert consuming all gas in that case - precompileCost := gasToPass // just in case - } - - switch isStatic + switch lt(gasToPass, precompileCost) case 0 { - success := rawCall(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + let zkVmGasToPass := gas() // pass all remaining gas, precompiles should not call any contracts + + switch isStatic + case 0 { + success := rawCall(zkVmGasToPass, addr, value, argsOffset, argsSize, retOffset, retSize) + } + default { + success := rawStaticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) + } + + _saveReturndataAfterZkEVMCall() + + if success { + frameGasLeft := sub(gasToPass, precompileCost) + } + // else consume all provided gas } default { - success := rawStaticcall(zkVmGasToPass, addr, argsOffset, argsSize, retOffset, retSize) - } - - _saveReturndataAfterZkEVMCall() - - if success { - frameGasLeft := sub(gasToPass, precompileCost) + // consume all provided gas + _eraseReturndataPointer() } - // else consume all provided gas } // Call native ZkVm contract from EVM context From daf70229288555d4d1ade61b7e97bf01564502c7 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 9 Dec 2024 12:41:38 +0100 Subject: [PATCH 178/183] fix(EVM): Fix logs implementation (2) (#1137) --- system-contracts/contracts/EvmEmulator.yul | 250 ++++++------------ .../EvmEmulatorFunctions.template.yul | 29 ++ .../evm-emulator/EvmEmulatorLoop.template.yul | 96 +------ 3 files changed, 117 insertions(+), 258 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 367aa87c9..ea8b65d34 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1301,6 +1301,35 @@ object "EvmEmulator" { $llvm_AlwaysInline_llvm$_copyRest(dest_end, 0, rest_len) } } + + //////////////////////////////////////////////////////////////// + // LOGS FUNCTIONALITY + //////////////////////////////////////////////////////////////// + + function _genericLog(sp, stackHead, evmGasLeft, topicCount, isStatic) -> newEvmGasLeft, offset, size, newSp, newStackHead { + newEvmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + panic() + } + + let rawOffset + popStackCheck(sp, add(2, topicCount)) + rawOffset, newSp, newStackHead := popStackItemWithoutCheck(sp, stackHead) + size, newSp, newStackHead := popStackItemWithoutCheck(newSp, newStackHead) + + checkMemIsAccessible(rawOffset, size) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(rawOffset, size)) + dynamicGas := add(dynamicGas, mul(375, topicCount)) + + newEvmGasLeft := chargeGas(newEvmGasLeft, dynamicGas) + + if size { + offset := add(rawOffset, MEM_OFFSET()) + } + } function simulate( isCallerEVM, @@ -2641,125 +2670,49 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0xA0 { // OP_LOG0 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 2) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - - log0(add(offset, MEM_OFFSET()), size) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 0, isStatic) + log0(offset, size) ip := add(ip, 1) } case 0xA1 { // OP_LOG1 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 3) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 375) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 1, isStatic) { let topic1 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log1(add(offset, MEM_OFFSET()), size, topic1) + log1(offset, size, topic1) } ip := add(ip, 1) } case 0xA2 { // OP_LOG2 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 4) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 750) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 2, isStatic) { let topic1, topic2 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log2(add(offset, MEM_OFFSET()), size, topic1, topic2) + log2(offset, size, topic1, topic2) } ip := add(ip, 1) } case 0xA3 { // OP_LOG3 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 5) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 1125) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 3, isStatic) { let topic1, topic2, topic3 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log3(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3) + log3(offset, size, topic1, topic2, topic3) } ip := add(ip, 1) } case 0xA4 { // OP_LOG4 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 6) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 1500) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 4, isStatic) { let topic1, topic2, topic3, topic4 @@ -2767,7 +2720,7 @@ object "EvmEmulator" { topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log4(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3, topic4) + log4(offset, size, topic1, topic2, topic3, topic4) } ip := add(ip, 1) } @@ -4488,6 +4441,35 @@ object "EvmEmulator" { $llvm_AlwaysInline_llvm$_copyRest(dest_end, 0, rest_len) } } + + //////////////////////////////////////////////////////////////// + // LOGS FUNCTIONALITY + //////////////////////////////////////////////////////////////// + + function _genericLog(sp, stackHead, evmGasLeft, topicCount, isStatic) -> newEvmGasLeft, offset, size, newSp, newStackHead { + newEvmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + panic() + } + + let rawOffset + popStackCheck(sp, add(2, topicCount)) + rawOffset, newSp, newStackHead := popStackItemWithoutCheck(sp, stackHead) + size, newSp, newStackHead := popStackItemWithoutCheck(newSp, newStackHead) + + checkMemIsAccessible(rawOffset, size) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(rawOffset, size)) + dynamicGas := add(dynamicGas, mul(375, topicCount)) + + newEvmGasLeft := chargeGas(newEvmGasLeft, dynamicGas) + + if size { + offset := add(rawOffset, MEM_OFFSET()) + } + } function $llvm_NoInline_llvm$_simulate( isCallerEVM, @@ -5828,125 +5810,49 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0xA0 { // OP_LOG0 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 2) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - - log0(add(offset, MEM_OFFSET()), size) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 0, isStatic) + log0(offset, size) ip := add(ip, 1) } case 0xA1 { // OP_LOG1 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 3) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 375) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 1, isStatic) { let topic1 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log1(add(offset, MEM_OFFSET()), size, topic1) + log1(offset, size, topic1) } ip := add(ip, 1) } case 0xA2 { // OP_LOG2 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 4) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 750) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 2, isStatic) { let topic1, topic2 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log2(add(offset, MEM_OFFSET()), size, topic1, topic2) + log2(offset, size, topic1, topic2) } ip := add(ip, 1) } case 0xA3 { // OP_LOG3 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 5) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 1125) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 3, isStatic) { let topic1, topic2, topic3 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log3(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3) + log3(offset, size, topic1, topic2, topic3) } ip := add(ip, 1) } case 0xA4 { // OP_LOG4 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 6) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 1500) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 4, isStatic) { let topic1, topic2, topic3, topic4 @@ -5954,7 +5860,7 @@ object "EvmEmulator" { topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log4(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3, topic4) + log4(offset, size, topic1, topic2, topic3, topic4) } ip := add(ip, 1) } diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 00d579de5..50089c79d 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -1238,4 +1238,33 @@ function $llvm_AlwaysInline_llvm$_memsetToZero(dest,len) { if rest_len { $llvm_AlwaysInline_llvm$_copyRest(dest_end, 0, rest_len) } +} + +//////////////////////////////////////////////////////////////// +// LOGS FUNCTIONALITY +//////////////////////////////////////////////////////////////// + +function _genericLog(sp, stackHead, evmGasLeft, topicCount, isStatic) -> newEvmGasLeft, offset, size, newSp, newStackHead { + newEvmGasLeft := chargeGas(evmGasLeft, 375) + + if isStatic { + panic() + } + + let rawOffset + popStackCheck(sp, add(2, topicCount)) + rawOffset, newSp, newStackHead := popStackItemWithoutCheck(sp, stackHead) + size, newSp, newStackHead := popStackItemWithoutCheck(newSp, newStackHead) + + checkMemIsAccessible(rawOffset, size) + + // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost + let dynamicGas := add(shl(3, size), expandMemory(rawOffset, size)) + dynamicGas := add(dynamicGas, mul(375, topicCount)) + + newEvmGasLeft := chargeGas(newEvmGasLeft, dynamicGas) + + if size { + offset := add(rawOffset, MEM_OFFSET()) + } } \ No newline at end of file diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index e1eeae682..b5d956b44 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -1328,125 +1328,49 @@ for { } true { } { ip := add(ip, 1) } case 0xA0 { // OP_LOG0 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 2) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - - log0(add(offset, MEM_OFFSET()), size) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 0, isStatic) + log0(offset, size) ip := add(ip, 1) } case 0xA1 { // OP_LOG1 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 3) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 375) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) - + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 1, isStatic) { let topic1 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log1(add(offset, MEM_OFFSET()), size, topic1) + log1(offset, size, topic1) } ip := add(ip, 1) } case 0xA2 { // OP_LOG2 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 4) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 750) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 2, isStatic) { let topic1, topic2 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log2(add(offset, MEM_OFFSET()), size, topic1, topic2) + log2(offset, size, topic1, topic2) } ip := add(ip, 1) } case 0xA3 { // OP_LOG3 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 5) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 1125) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 3, isStatic) { let topic1, topic2, topic3 topic1, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log3(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3) + log3(offset, size, topic1, topic2, topic3) } ip := add(ip, 1) } case 0xA4 { // OP_LOG4 - evmGasLeft := chargeGas(evmGasLeft, 375) - - if isStatic { - panic() - } - let offset, size - popStackCheck(sp, 6) - offset, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - size, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - - checkMemIsAccessible(offset, size) - - // dynamicGas = 375 * topic_count + 8 * size + memory_expansion_cost - let dynamicGas := add(shl(3, size), expandMemory(offset, size)) - dynamicGas := add(dynamicGas, 1500) - evmGasLeft := chargeGas(evmGasLeft, dynamicGas) + evmGasLeft, offset, size, sp, stackHead := _genericLog(sp, stackHead, evmGasLeft, 4, isStatic) { let topic1, topic2, topic3, topic4 @@ -1454,7 +1378,7 @@ for { } true { } { topic2, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic3, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) topic4, sp, stackHead := popStackItemWithoutCheck(sp, stackHead) - log4(add(offset, MEM_OFFSET()), size, topic1, topic2, topic3, topic4) + log4(offset, size, topic1, topic2, topic3, topic4) } ip := add(ip, 1) } From fe838fcbd6479cb98262bbaa4a8752236bc6fdf4 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Mon, 16 Dec 2024 18:35:43 +0100 Subject: [PATCH 179/183] feat(EVM): Enable EVM emulator using service call (#1141) --- l1-contracts/contracts/common/Config.sol | 3 ++ .../common/interfaces/IL2ContractDeployer.sol | 12 ++++++ .../contracts/governance/ChainAdmin.sol | 7 ++++ .../contracts/governance/IChainAdmin.sol | 5 +++ .../StateTransitionManager.sol | 34 +++++------------ .../chain-deps/facets/Admin.sol | 12 ++++++ .../chain-deps/facets/Mailbox.sol | 37 +++++++++++++++++- .../facets/ZkSyncHyperchainBase.sol | 7 ++++ .../chain-interfaces/IAdmin.sol | 6 +++ .../chain-interfaces/IMailbox.sol | 9 +++++ .../l2-deps/AllowedBytecodeTypes.sol | 11 ------ .../l2-deps/ISystemContext.sol | 5 +-- .../deploy-scripts/EnableEvmEmulator.s.sol | 18 +++++++++ .../PrepareZKChainRegistrationCalldata.s.sol | 10 +---- .../deploy-scripts/RegisterHyperchain.s.sol | 10 +---- l1-contracts/scripts/register-hyperchain.ts | 13 ++++--- l1-contracts/src.ts/deploy-process.ts | 6 +-- l1-contracts/src.ts/deploy.ts | 22 ++++++----- .../Bridgehub/experimental_bridge.t.sol | 15 ++------ .../CreateNewChain.t.sol | 3 +- .../_StateTransitionManager_Shared.t.sol | 15 +------- system-contracts/SystemContractsHashes.json | 38 +++++++++---------- system-contracts/contracts/Constants.sol | 4 +- .../contracts/ContractDeployer.sol | 17 +++------ system-contracts/contracts/SystemContext.sol | 13 +------ .../contracts/SystemContractErrors.sol | 2 - .../interfaces/IContractDeployer.sol | 4 +- 27 files changed, 185 insertions(+), 153 deletions(-) delete mode 100644 l1-contracts/contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol create mode 100644 l1-contracts/deploy-scripts/EnableEvmEmulator.s.sol diff --git a/l1-contracts/contracts/common/Config.sol b/l1-contracts/contracts/common/Config.sol index c0e05f1fc..e6e3118bb 100644 --- a/l1-contracts/contracts/common/Config.sol +++ b/l1-contracts/contracts/common/Config.sol @@ -108,3 +108,6 @@ bytes32 constant TWO_BRIDGES_MAGIC_VALUE = bytes32(uint256(keccak256("TWO_BRIDGE /// @dev https://eips.ethereum.org/EIPS/eip-1352 address constant BRIDGEHUB_MIN_SECOND_BRIDGE_ADDRESS = address(uint160(type(uint16).max)); + +/// @dev Used as the `msg.sender` for system service transactions. +address constant SERVICE_TRANSACTION_SENDER = address(uint160(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF)); diff --git a/l1-contracts/contracts/common/interfaces/IL2ContractDeployer.sol b/l1-contracts/contracts/common/interfaces/IL2ContractDeployer.sol index 3d5b597df..7aa5c1cc0 100644 --- a/l1-contracts/contracts/common/interfaces/IL2ContractDeployer.sol +++ b/l1-contracts/contracts/common/interfaces/IL2ContractDeployer.sol @@ -2,6 +2,14 @@ // 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.21; +/// @notice Defines what types of bytecode are allowed to be deployed on this chain +/// - `EraVm` means that only native contracts can be deployed +/// - `EraVmAndEVM` means that native contracts and EVM contracts can be deployed +enum AllowedBytecodeTypes { + EraVm, + EraVmAndEVM +} + /** * @author Matter Labs * @notice System smart contract that is responsible for deploying other smart contracts on a ZKsync hyperchain. @@ -29,4 +37,8 @@ interface IL2ContractDeployer { /// @param _bytecodeHash The correctly formatted hash of the bytecode. /// @param _input The constructor calldata. function create2(bytes32 _salt, bytes32 _bytecodeHash, bytes calldata _input) external; + + /// @notice Changes what types of bytecodes are allowed to be deployed on the chain. + /// @param newAllowedBytecodeTypes The new allowed bytecode types mode. + function setAllowedBytecodeTypesToDeploy(AllowedBytecodeTypes newAllowedBytecodeTypes) external; } diff --git a/l1-contracts/contracts/governance/ChainAdmin.sol b/l1-contracts/contracts/governance/ChainAdmin.sol index 4d9ff858f..c322477a7 100644 --- a/l1-contracts/contracts/governance/ChainAdmin.sol +++ b/l1-contracts/contracts/governance/ChainAdmin.sol @@ -48,6 +48,13 @@ contract ChainAdmin is IChainAdmin, Ownable2Step { emit UpdateUpgradeTimestamp(_protocolVersion, _upgradeTimestamp); } + /// @notice Enable EVM emulation on chain. + /// @param _chainContract The chain contract address where the EVM emulator will be enabled. + function enableEvmEmulator(IAdmin _chainContract) external onlyOwner returns (bytes32 canonicalTxHash) { + canonicalTxHash = _chainContract.allowEvmEmulation(); + emit EnableEvmEmulator(); + } + /// @notice Execute multiple calls as part of contract administration. /// @param _calls Array of Call structures defining target, value, and data for each call. /// @param _requireSuccess If true, reverts transaction on any call failure. diff --git a/l1-contracts/contracts/governance/IChainAdmin.sol b/l1-contracts/contracts/governance/IChainAdmin.sol index d5d8f117c..5bdd15ac9 100644 --- a/l1-contracts/contracts/governance/IChainAdmin.sol +++ b/l1-contracts/contracts/governance/IChainAdmin.sol @@ -27,6 +27,9 @@ interface IChainAdmin { /// @notice Emitted when the new token multiplier address is set. event NewTokenMultiplierSetter(address _oldTokenMultiplierSetter, address _newTokenMultiplierSetter); + /// @notice The EVM emulator has been enabled + event EnableEvmEmulator(); + function setTokenMultiplierSetter(address _tokenMultiplierSetter) external; function setUpgradeTimestamp(uint256 _protocolVersion, uint256 _upgradeTimestamp) external; @@ -34,4 +37,6 @@ interface IChainAdmin { function multicall(Call[] calldata _calls, bool _requireSuccess) external payable; function setTokenMultiplier(IAdmin _chainContract, uint128 _nominator, uint128 _denominator) external; + + function enableEvmEmulator(IAdmin _chainContract) external returns (bytes32 canonicalTxHash); } diff --git a/l1-contracts/contracts/state-transition/StateTransitionManager.sol b/l1-contracts/contracts/state-transition/StateTransitionManager.sol index f610bad78..a14298f2a 100644 --- a/l1-contracts/contracts/state-transition/StateTransitionManager.sol +++ b/l1-contracts/contracts/state-transition/StateTransitionManager.sol @@ -13,7 +13,6 @@ import {IDiamondInit} from "./chain-interfaces/IDiamondInit.sol"; import {IExecutor} from "./chain-interfaces/IExecutor.sol"; import {IStateTransitionManager, StateTransitionManagerInitializeData, ChainCreationParams} from "./IStateTransitionManager.sol"; import {ISystemContext} from "./l2-deps/ISystemContext.sol"; -import {AllowedBytecodeTypes} from "./l2-deps/AllowedBytecodeTypes.sol"; import {IZkSyncHyperchain} from "./chain-interfaces/IZkSyncHyperchain.sol"; import {FeeParams} from "./chain-deps/ZkSyncHyperchainStorage.sol"; import {L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR, L2_FORCE_DEPLOYER_ADDR} from "../common/L2ContractAddresses.sol"; @@ -323,15 +322,8 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own /// registration /// @dev we have to set the chainId at genesis, as blockhashzero is the same for all chains with the same chainId - function _setChainConfigurationUpgrade( - uint256 _chainId, - AllowedBytecodeTypes _allowedBytecodeTypesMode, - address _chainContract - ) internal { - bytes memory systemContextCalldata = abi.encodeCall( - ISystemContext.setChainConfiguration, - (_chainId, uint256(_allowedBytecodeTypesMode)) - ); + function _setChainIdUpgrade(uint256 _chainId, address _chainContract) internal { + bytes memory systemContextCalldata = abi.encodeCall(ISystemContext.setChainId, (_chainId)); uint256[] memory uintEmptyArray; bytes[] memory bytesEmptyArray; @@ -404,13 +396,13 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own /// @param _baseToken the base token address used to pay for gas fees /// @param _sharedBridge the shared bridge address, used as base token bridge /// @param _admin the chain's admin address - /// @param _inputData the input data for chain creation + /// @param _diamondCut the diamond cut data that initializes the chains Diamond Proxy function createNewChain( uint256 _chainId, address _baseToken, address _sharedBridge, address _admin, - bytes calldata _inputData + bytes calldata _diamondCut ) external onlyBridgehub { if (getHyperchain(_chainId) != address(0)) { // Hyperchain already registered @@ -418,18 +410,12 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own } // check not registered - (bytes memory _diamondCut, AllowedBytecodeTypes allowedBytecodeTypesMode) = abi.decode( - _inputData, - (bytes, AllowedBytecodeTypes) - ); Diamond.DiamondCutData memory diamondCut = abi.decode(_diamondCut, (Diamond.DiamondCutData)); - { - // check input - bytes32 cutHashInput = keccak256(_diamondCut); - if (cutHashInput != initialCutHash) { - revert HashMismatch(initialCutHash, cutHashInput); - } + // check input + bytes32 cutHashInput = keccak256(_diamondCut); + if (cutHashInput != initialCutHash) { + revert HashMismatch(initialCutHash, cutHashInput); } // construct init data @@ -459,8 +445,8 @@ contract StateTransitionManager is IStateTransitionManager, ReentrancyGuard, Own _registerNewHyperchain(_chainId, hyperchainAddress); - // set chain configuration: chainId in VM and allowed bytecode types - _setChainConfigurationUpgrade(_chainId, allowedBytecodeTypesMode, hyperchainAddress); + // set chainId in VM + _setChainIdUpgrade(_chainId, hyperchainAddress); } /// @dev This internal function is used to register a new hyperchain in the system. diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol index 9f98c00ec..479f4bbdb 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol @@ -3,12 +3,15 @@ pragma solidity 0.8.24; import {IAdmin} from "../../chain-interfaces/IAdmin.sol"; +import {IMailbox} from "../../chain-interfaces/IMailbox.sol"; import {Diamond} from "../../libraries/Diamond.sol"; import {MAX_GAS_PER_TRANSACTION} from "../../../common/Config.sol"; import {FeeParams, PubdataPricingMode} from "../ZkSyncHyperchainStorage.sol"; import {ZkSyncHyperchainBase} from "./ZkSyncHyperchainBase.sol"; import {IStateTransitionManager} from "../../IStateTransitionManager.sol"; import {Unauthorized, TooMuchGas, PriorityTxPubdataExceedsMaxPubDataPerBatch, InvalidPubdataPricingMode, ProtocolIdMismatch, ChainAlreadyLive, HashMismatch, ProtocolIdNotGreater, DenominatorIsZero, DiamondAlreadyFrozen, DiamondNotFrozen} from "../../../common/L1ContractErrors.sol"; +import {L2_DEPLOYER_SYSTEM_CONTRACT_ADDR} from "../../../common/L2ContractAddresses.sol"; +import {IL2ContractDeployer, AllowedBytecodeTypes} from "../../../common/interfaces/IL2ContractDeployer.sol"; // While formally the following import is not used, it is needed to inherit documentation from it import {IZkSyncHyperchainBase} from "../../chain-interfaces/IZkSyncHyperchainBase.sol"; @@ -119,6 +122,15 @@ contract AdminFacet is ZkSyncHyperchainBase, IAdmin { emit NewTransactionFilterer(oldTransactionFilterer, _transactionFilterer); } + /// @inheritdoc IAdmin + function allowEvmEmulation() external onlyAdmin returns (bytes32 canonicalTxHash) { + canonicalTxHash = IMailbox(address(this)).requestL2ServiceTransaction( + L2_DEPLOYER_SYSTEM_CONTRACT_ADDR, + abi.encodeCall(IL2ContractDeployer.setAllowedBytecodeTypesToDeploy, AllowedBytecodeTypes.EraVmAndEVM) + ); + emit EnableEvmEmulator(); + } + /*////////////////////////////////////////////////////////////// UPGRADE EXECUTION //////////////////////////////////////////////////////////////*/ diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Mailbox.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Mailbox.sol index 43f6b04e7..771c66176 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Mailbox.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Mailbox.sol @@ -15,7 +15,7 @@ import {UncheckedMath} from "../../../common/libraries/UncheckedMath.sol"; import {L2ContractHelper} from "../../../common/libraries/L2ContractHelper.sol"; import {AddressAliasHelper} from "../../../vendor/AddressAliasHelper.sol"; import {ZkSyncHyperchainBase} from "./ZkSyncHyperchainBase.sol"; -import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA, ETH_TOKEN_ADDRESS, L1_GAS_PER_PUBDATA_BYTE, L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH, PRIORITY_OPERATION_L2_TX_TYPE, PRIORITY_EXPIRATION, MAX_NEW_FACTORY_DEPS} from "../../../common/Config.sol"; +import {REQUIRED_L2_GAS_PRICE_PER_PUBDATA, ETH_TOKEN_ADDRESS, L1_GAS_PER_PUBDATA_BYTE, L2_L1_LOGS_TREE_DEFAULT_LEAF_HASH, PRIORITY_OPERATION_L2_TX_TYPE, PRIORITY_EXPIRATION, MAX_NEW_FACTORY_DEPS, SERVICE_TRANSACTION_SENDER} from "../../../common/Config.sol"; import {L2_BOOTLOADER_ADDRESS, L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR} from "../../../common/L2ContractAddresses.sol"; import {IL1SharedBridge} from "../../../bridge/interfaces/IL1SharedBridge.sol"; @@ -248,6 +248,28 @@ contract MailboxFacet is ZkSyncHyperchainBase, IMailbox { ); } + /// @inheritdoc IMailbox + function requestL2ServiceTransaction( + address _contractL2, + bytes calldata _l2Calldata + ) external onlySelf returns (bytes32 canonicalTxHash) { + canonicalTxHash = _requestL2TransactionFree( + BridgehubL2TransactionRequest({ + sender: SERVICE_TRANSACTION_SENDER, + contractL2: _contractL2, + mintValue: 0, + l2Value: 0, + // Very large amount + l2GasLimit: 72_000_000, + l2Calldata: _l2Calldata, + l2GasPerPubdataByteLimit: REQUIRED_L2_GAS_PRICE_PER_PUBDATA, + factoryDeps: new bytes[](0), + // Tx is free, so no refund recipient needed + refundRecipient: address(0) + }) + ); + } + function _requestL2TransactionSender( BridgehubL2TransactionRequest memory _request ) internal nonReentrant returns (bytes32 canonicalTxHash) { @@ -313,6 +335,19 @@ contract MailboxFacet is ZkSyncHyperchainBase, IMailbox { canonicalTxHash = _writePriorityOp(_params); } + function _requestL2TransactionFree( + BridgehubL2TransactionRequest memory _request + ) internal nonReentrant returns (bytes32 canonicalTxHash) { + WritePriorityOpParams memory params = WritePriorityOpParams({ + request: _request, + txId: s.priorityQueue.getTotalPriorityTxs(), + l2GasPrice: 0, + expirationTimestamp: uint64(block.timestamp + PRIORITY_EXPIRATION) + }); + + canonicalTxHash = _writePriorityOp(params); + } + function _serializeL2Transaction( WritePriorityOpParams memory _priorityOpParams ) internal pure returns (L2CanonicalTransaction memory transaction) { diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/ZkSyncHyperchainBase.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/ZkSyncHyperchainBase.sol index 0910fcab3..8d6bbb4ce 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/ZkSyncHyperchainBase.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/ZkSyncHyperchainBase.sol @@ -64,4 +64,11 @@ contract ZkSyncHyperchainBase is ReentrancyGuard { } _; } + + modifier onlySelf() { + if (msg.sender != address(this)) { + revert Unauthorized(msg.sender); + } + _; + } } diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol index 643c6114d..6771c349f 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IAdmin.sol @@ -46,6 +46,9 @@ interface IAdmin is IZkSyncHyperchainBase { /// @notice Set the transaction filterer function setTransactionFilterer(address _transactionFilterer) external; + /// @notice Allow EVM emulation on chain + function allowEvmEmulation() external returns (bytes32 canonicalTxHash); + /// @notice Perform the upgrade from the current protocol version with the corresponding upgrade data /// @param _protocolVersion The current protocol version from which upgrade is executed /// @param _cutData The diamond cut parameters that is executed in the upgrade @@ -105,4 +108,7 @@ interface IAdmin is IZkSyncHyperchainBase { /// @notice Emitted when the contract is unfrozen. event Unfreeze(); + + /// @notice The EVM emulator has been enabled + event EnableEvmEmulator(); } diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IMailbox.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IMailbox.sol index 9daffebcf..563fcb12e 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IMailbox.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IMailbox.sol @@ -95,6 +95,15 @@ interface IMailbox is IZkSyncHyperchainBase { address _refundRecipient ) external payable returns (bytes32 canonicalTxHash); + /// @notice Request execution of service L2 transaction from L1. + /// @dev Used for chain configuration. Can be called only by DiamondProxy itself. + /// @param _contractL2 The L2 receiver address + /// @param _l2Calldata The input of the L2 transaction + function requestL2ServiceTransaction( + address _contractL2, + bytes calldata _l2Calldata + ) external returns (bytes32 canonicalTxHash); + function bridgehubRequestL2Transaction( BridgehubL2TransactionRequest calldata _request ) external returns (bytes32 canonicalTxHash); diff --git a/l1-contracts/contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol b/l1-contracts/contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol deleted file mode 100644 index 2d6a3a136..000000000 --- a/l1-contracts/contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT -// 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.21; - -/// @notice Defines what types of bytecode are allowed to be deployed on this chain -/// - `EraVm` means that only native contracts can be deployed -/// - `EraVmAndEVM` means that native contracts and EVM contracts can be deployed -enum AllowedBytecodeTypes { - EraVm, - EraVmAndEVM -} diff --git a/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.sol b/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.sol index cdc1140e7..d3244b74b 100644 --- a/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.sol +++ b/l1-contracts/contracts/state-transition/l2-deps/ISystemContext.sol @@ -3,8 +3,5 @@ pragma solidity ^0.8.21; interface ISystemContext { - /// @notice Set the chain configuration. - /// @param _newChainId The chainId - /// @param _newAllowedBytecodeTypes The new allowed bytecode types mode. - function setChainConfiguration(uint256 _newChainId, uint256 _newAllowedBytecodeTypes) external; + function setChainId(uint256 _newChainId) external; } diff --git a/l1-contracts/deploy-scripts/EnableEvmEmulator.s.sol b/l1-contracts/deploy-scripts/EnableEvmEmulator.s.sol new file mode 100644 index 000000000..5e9d466ce --- /dev/null +++ b/l1-contracts/deploy-scripts/EnableEvmEmulator.s.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.21; + +import {Script} from "forge-std/Script.sol"; + +import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol"; +import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; + +contract EnableEvmEmulator is Script { + // This function should be called by the owner to update token multiplier setter role + function chainAllowEvmEmulation(address chainAdmin, address target) public { + IChainAdmin admin = IChainAdmin(chainAdmin); + + vm.startBroadcast(); + admin.enableEvmEmulator(IZkSyncHyperchain(target)); + vm.stopBroadcast(); + } +} diff --git a/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol b/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol index a965704b6..c2d48f322 100644 --- a/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol +++ b/l1-contracts/deploy-scripts/PrepareZKChainRegistrationCalldata.s.sol @@ -12,9 +12,7 @@ import {L2ContractHelper} from "contracts/common/libraries/L2ContractHelper.sol" import {AddressAliasHelper} from "contracts/vendor/AddressAliasHelper.sol"; import {L1SharedBridge} from "contracts/bridge/L1SharedBridge.sol"; import {IStateTransitionManager} from "contracts/state-transition/IStateTransitionManager.sol"; -import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {IGovernance} from "contracts/governance/IGovernance.sol"; -import {IChainAdmin} from "contracts/governance/IChainAdmin.sol"; import {Call} from "contracts/governance/Common.sol"; import {Utils} from "./Utils.sol"; @@ -276,12 +274,6 @@ contract PrepareZKChainRegistrationCalldataScript is Script { function prepareRegisterHyperchainCall() internal view returns (Call memory) { Bridgehub bridgehub = Bridgehub(ecosystem.bridgehub); - AllowedBytecodeTypes allowedBytecodeTypesMode = config.allowEvmEmulator - ? AllowedBytecodeTypes.EraVmAndEVM - : AllowedBytecodeTypes.EraVm; - - bytes memory diamondCutEncoded = abi.encode(config.diamondCutData); - bytes memory data = abi.encodeCall( bridgehub.createNewChain, ( @@ -290,7 +282,7 @@ contract PrepareZKChainRegistrationCalldataScript is Script { config.baseToken, config.bridgehubCreateNewChainSalt, config.chainAdmin, - abi.encode(diamondCutEncoded, allowedBytecodeTypesMode) + config.diamondCutData ) ); diff --git a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol index 7dfa127d2..9a8c5f781 100644 --- a/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol +++ b/l1-contracts/deploy-scripts/RegisterHyperchain.s.sol @@ -9,7 +9,6 @@ import {stdToml} from "forge-std/StdToml.sol"; import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {IZkSyncHyperchain} from "contracts/state-transition/chain-interfaces/IZkSyncHyperchain.sol"; -import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {ValidatorTimelock} from "contracts/state-transition/ValidatorTimelock.sol"; import {Governance} from "contracts/governance/Governance.sol"; import {ChainAdmin} from "contracts/governance/ChainAdmin.sol"; @@ -157,14 +156,7 @@ contract RegisterHyperchainScript is Script { function registerHyperchain() internal { Bridgehub bridgehub = Bridgehub(config.bridgehub); - AllowedBytecodeTypes allowedBytecodeTypesMode = config.allowEvmEmulator - ? AllowedBytecodeTypes.EraVmAndEVM - : AllowedBytecodeTypes.EraVm; - - bytes memory initData = abi.encode(config.diamondCutData, allowedBytecodeTypesMode); - vm.recordLogs(); - bytes memory data = abi.encodeCall( bridgehub.createNewChain, ( @@ -173,7 +165,7 @@ contract RegisterHyperchainScript is Script { config.baseToken, config.bridgehubCreateNewChainSalt, msg.sender, - initData + config.diamondCutData ) ); diff --git a/l1-contracts/scripts/register-hyperchain.ts b/l1-contracts/scripts/register-hyperchain.ts index 587edec2e..485eb3579 100644 --- a/l1-contracts/scripts/register-hyperchain.ts +++ b/l1-contracts/scripts/register-hyperchain.ts @@ -107,10 +107,6 @@ async function main() { const tokenMultiplierSetterAddress = cmd.tokenMultiplierSetterAddress || ""; - const isEvmEmulatorSupported = !!cmd.allowEvmEmulation; - - console.log(`EVM emulator: ${isEvmEmulatorSupported ? "SUPPORTED" : " NOT SUPPORTED"}`); - await deployer.registerHyperchain( baseTokenAddress, cmd.validiumMode, @@ -119,13 +115,18 @@ async function main() { null, null, null, - useGovernance, - isEvmEmulatorSupported + useGovernance ); if (tokenMultiplierSetterAddress != "") { console.log(`Using token multiplier setter address: ${tokenMultiplierSetterAddress}`); await deployer.setTokenMultiplierSetterAddress(tokenMultiplierSetterAddress); } + + if (cmd.allowEvmEmulation) { + console.log("Allowing EVM emulation"); + await deployer.enableEvmEmulation(); + } + await deployer.transferAdminFromDeployerToChainAdmin(); }); diff --git a/l1-contracts/src.ts/deploy-process.ts b/l1-contracts/src.ts/deploy-process.ts index 1e1a00be2..e9622bfbe 100644 --- a/l1-contracts/src.ts/deploy-process.ts +++ b/l1-contracts/src.ts/deploy-process.ts @@ -80,8 +80,7 @@ export async function registerHyperchain( gasPrice: BigNumberish, baseTokenName?: string, chainId?: string, - useGovernance: boolean = false, - isEvmEmulatorSupported: boolean = false + useGovernance: boolean = false ) { const testnetTokens = getTokens(); @@ -100,7 +99,6 @@ export async function registerHyperchain( false, null, chainId, - useGovernance, - isEvmEmulatorSupported + useGovernance ); } diff --git a/l1-contracts/src.ts/deploy.ts b/l1-contracts/src.ts/deploy.ts index 7b96f6358..dfc16a810 100644 --- a/l1-contracts/src.ts/deploy.ts +++ b/l1-contracts/src.ts/deploy.ts @@ -734,8 +734,7 @@ export class Deployer { compareDiamondCutHash: boolean = false, nonce?, predefinedChainId?: string, - useGovernance: boolean = false, - isEvmEmulatorSupported: boolean = false + useGovernance: boolean = false ) { const gasLimit = 10_000_000; @@ -749,12 +748,6 @@ export class Deployer { const diamondCutData = await this.initialZkSyncHyperchainDiamondCut(extraFacets, compareDiamondCutHash); const diamondCutDataEncoded = new ethers.utils.AbiCoder().encode([DIAMOND_CUT_DATA_ABI_STRING], [diamondCutData]); - const allowedBytecodeTypesMode = isEvmEmulatorSupported ? 1 : 0; - const initData = new ethers.utils.AbiCoder().encode( - ["bytes", "uint256"], - [diamondCutDataEncoded, allowedBytecodeTypesMode] - ); - const receipt = await this.executeDirectOrGovernance( useGovernance, bridgehub, @@ -765,7 +758,7 @@ export class Deployer { baseTokenAddress, Date.now(), admin, - initData, + diamondCutDataEncoded, ], 0, { @@ -871,6 +864,17 @@ export class Deployer { } } + public async enableEvmEmulation() { + const stm = this.stateTransitionManagerContract(this.deployWallet); + const diamondProxyAddress = await stm.getHyperchain(this.chainId); + const hyperchain = IZkSyncHyperchainFactory.connect(diamondProxyAddress, this.deployWallet); + + const receipt = await (await hyperchain.allowEvmEmulation()).wait(); + if (this.verbose) { + console.log(`EVM emulation allowed, gas used: ${receipt.gasUsed.toString()}`); + } + } + public async transferAdminFromDeployerToChainAdmin() { const stm = this.stateTransitionManagerContract(this.deployWallet); const diamondProxyAddress = await stm.getHyperchain(this.chainId); diff --git a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol index 32fd846db..43826e6ac 100644 --- a/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Bridgehub/experimental_bridge.t.sol @@ -8,7 +8,6 @@ import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; import {TestnetERC20Token} from "contracts/dev-contracts/TestnetERC20Token.sol"; import {Bridgehub} from "contracts/bridgehub/Bridgehub.sol"; import {ChainCreationParams} from "contracts/state-transition/IStateTransitionManager.sol"; -import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {L2TransactionRequestDirect, L2TransactionRequestTwoBridgesOuter} from "contracts/bridgehub/IBridgehub.sol"; import {DummyStateTransitionManagerWBH} from "contracts/dev-contracts/test/DummyStateTransitionManagerWithBridgeHubAddress.sol"; import {DummyHyperchain} from "contracts/dev-contracts/test/DummyHyperchain.sol"; @@ -662,8 +661,7 @@ contract ExperimentalBridgeTest is Test { isFreezable, mockSelectors, mockInitAddress, - mockInitCalldata, - false + mockInitCalldata ); // bridgeHub.createNewChain => stateTransitionManager.createNewChain => this function sets the stateTransition mapping @@ -1433,8 +1431,7 @@ contract ExperimentalBridgeTest is Test { bool isFreezable, bytes4[] memory mockSelectors, address, //mockInitAddress, - bytes memory, //mockInitCalldata - bool allowEvmEmulation + bytes memory //mockInitCalldata ) internal returns (bytes memory) { bytes4[] memory singleSelector = new bytes4[](1); singleSelector[0] = bytes4(0xabcdef12); @@ -1468,13 +1465,7 @@ contract ExperimentalBridgeTest is Test { mockSTM.setChainCreationParams(params); - bytes memory diamondCutEncoded = abi.encode(diamondCutData); - - AllowedBytecodeTypes allowedBytecodeTypesMode = allowEvmEmulation - ? AllowedBytecodeTypes.EraVmAndEVM - : AllowedBytecodeTypes.EraVm; - - return abi.encode(diamondCutEncoded, allowedBytecodeTypesMode); + return abi.encode(diamondCutData); } function _setUpHyperchainForChainId(uint256 mockChainId) internal returns (uint256 mockChainIdInRange) { diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol index 48cbb95b2..bce302a9b 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/CreateNewChain.t.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.24; import {StateTransitionManagerTest} from "./_StateTransitionManager_Shared.t.sol"; import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; -import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {Unauthorized, HashMismatch} from "contracts/common/L1ContractErrors.sol"; contract createNewChainTest is StateTransitionManagerTest { @@ -34,7 +33,7 @@ contract createNewChainTest is StateTransitionManagerTest { _baseToken: baseToken, _sharedBridge: sharedBridge, _admin: admin, - _inputData: getCreateInputData(initialDiamondCutData, false) + _diamondCut: abi.encode(initialDiamondCutData) }); } diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol index b13b1f920..80195e850 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/StateTransitionManager/_StateTransitionManager_Shared.t.sol @@ -17,7 +17,6 @@ import {DiamondInit} from "contracts/state-transition/chain-deps/DiamondInit.sol import {GenesisUpgrade} from "contracts/upgrades/GenesisUpgrade.sol"; import {InitializeDataNewChain} from "contracts/state-transition/chain-interfaces/IDiamondInit.sol"; import {StateTransitionManager} from "contracts/state-transition/StateTransitionManager.sol"; -import {AllowedBytecodeTypes} from "contracts/state-transition/l2-deps/AllowedBytecodeTypes.sol"; import {StateTransitionManagerInitializeData, ChainCreationParams} from "contracts/state-transition/IStateTransitionManager.sol"; import {TestnetVerifier} from "contracts/state-transition/TestnetVerifier.sol"; import {ZeroAddress} from "contracts/common/L1ContractErrors.sol"; @@ -129,18 +128,6 @@ contract StateTransitionManagerTest is Test { return Diamond.DiamondCutData({facetCuts: facetCuts, initAddress: _diamondInit, initCalldata: initCalldata}); } - function getCreateInputData( - Diamond.DiamondCutData memory _diamondCut, - bool allowEvmEmulator - ) internal view returns (bytes memory) { - bytes memory diamondCutEncoded = abi.encode(_diamondCut); - AllowedBytecodeTypes allowedBytecodeTypesMode = allowEvmEmulator - ? AllowedBytecodeTypes.EraVmAndEVM - : AllowedBytecodeTypes.EraVm; - - return abi.encode(diamondCutEncoded, allowedBytecodeTypesMode); - } - function createNewChain(Diamond.DiamondCutData memory _diamondCut) internal { _createNewChain(_diamondCut, false); } @@ -158,7 +145,7 @@ contract StateTransitionManagerTest is Test { _baseToken: baseToken, _sharedBridge: sharedBridge, _admin: newChainAdmin, - _inputData: getCreateInputData(_diamondCut, allowEvmEmulator) + _diamondCut: abi.encode(_diamondCut) }); } diff --git a/system-contracts/SystemContractsHashes.json b/system-contracts/SystemContractsHashes.json index f8c17571a..1bc5f5115 100644 --- a/system-contracts/SystemContractsHashes.json +++ b/system-contracts/SystemContractsHashes.json @@ -3,49 +3,49 @@ "contractName": "AccountCodeStorage", "bytecodePath": "zkout/AccountCodeStorage.sol/AccountCodeStorage.json", "sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol", - "bytecodeHash": "0x0100007317994a1fc65998cd916c99f52951e58cefedce3c330aacf7fd20dd94", + "bytecodeHash": "0x0100007360eb189d11c57c8b45bdd29ae2a996786b55e21847fbbe8e7b285ce2", "sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6" }, { "contractName": "BootloaderUtilities", "bytecodePath": "zkout/BootloaderUtilities.sol/BootloaderUtilities.json", "sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol", - "bytecodeHash": "0x010006f3eaa43c2aeece380d750965b772ae2d8874f942fe598445977118fd23", + "bytecodeHash": "0x010006f3bacfc75db6a91f2f2c05485c8f6d7ed0dd259b5d1a7de5bb5f0170a2", "sourceCodeHash": "0x10f30ac1a7098c7fddec2659ac43422783e8d3fdde02a3ba4d3ff45d451d7001" }, { "contractName": "ComplexUpgrader", "bytecodePath": "zkout/ComplexUpgrader.sol/ComplexUpgrader.json", "sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol", - "bytecodeHash": "0x010000470769b6a1ab43e898daf381c7df9753c51e8001e06b6daa39357f42a8", + "bytecodeHash": "0x01000047cfddb4597ec1fcff6ce1b13c404b128f8c7349943f00c8e702fcecd5", "sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614" }, { "contractName": "Compressor", "bytecodePath": "zkout/Compressor.sol/Compressor.json", "sourceCodePath": "contracts-preprocessed/Compressor.sol", - "bytecodeHash": "0x0100013f2c94736cbc8e992f7e84df5e01a64d15bf2443c2dda5bee7476c9575", + "bytecodeHash": "0x0100013f5b38355d5720b282db0cf3869b78e2c8d631550ef7a0f33e5757f6be", "sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5" }, { "contractName": "ContractDeployer", "bytecodePath": "zkout/ContractDeployer.sol/ContractDeployer.json", "sourceCodePath": "contracts-preprocessed/ContractDeployer.sol", - "bytecodeHash": "0x01000673f8b088c2c27ab36f025b222a908368fd22b461bf97b12784753b2fea", - "sourceCodeHash": "0xbb9a2717e6fd1da15df4ef1862d2e55e661547f973478bb1fc3cab1ea3cca575" + "bytecodeHash": "0x01000655cfaee8879d6d5f020e8cac9b00e5830a8aef6d01f9406b4583fa4bd8", + "sourceCodeHash": "0x22f96404a0527177f635c81315349ee274806e7462c5e5ae087a005f991bc157" }, { "contractName": "Create2Factory", "bytecodePath": "zkout/Create2Factory.sol/Create2Factory.json", "sourceCodePath": "contracts-preprocessed/Create2Factory.sol", - "bytecodeHash": "0x0100003ff00c4656ed039bac6da4b2f56c01acf662faff586f7032d33de48634", + "bytecodeHash": "0x0100003f53ff30da1f9c344e63c5a031affbf8af76baf0a92c977fefc8665a0c", "sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3" }, { "contractName": "DefaultAccount", "bytecodePath": "zkout/DefaultAccount.sol/DefaultAccount.json", "sourceCodePath": "contracts-preprocessed/DefaultAccount.sol", - "bytecodeHash": "0x0100050bcb0eb0f55ec0821967b509b2ae60fa52ff94f0f934b4de464e2f3a5d", + "bytecodeHash": "0x0100050b06623d83e54b5752821bc70b493f31989359002205a2f9264dba83f4", "sourceCodeHash": "0x300c864fcb3bc6a562875c7b1d83df15d466515da0a878a426b1aaeac26f3656" }, { @@ -59,57 +59,57 @@ "contractName": "ImmutableSimulator", "bytecodePath": "zkout/ImmutableSimulator.sol/ImmutableSimulator.json", "sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol", - "bytecodeHash": "0x010000338218e48deb166b7e6486e558038239530c8f30bdbc0b15dffc671aa6", + "bytecodeHash": "0x0100003345f92c227817a46a1cb0ee12cac25cb8516251a028f24d6cb1feb77b", "sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98" }, { "contractName": "KnownCodesStorage", "bytecodePath": "zkout/KnownCodesStorage.sol/KnownCodesStorage.json", "sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol", - "bytecodeHash": "0x010000cd7ef93ae3e09683ca91c705700694f3f9bd25f5d0d5fecd38d667eccf", + "bytecodeHash": "0x010000cde320e4772a0ef635bff69f07fd908a6140480cf2c17f2cf0214d86a3", "sourceCodeHash": "0x851fb5e170dfde39f1f9bc74654ec0b8f8f1d4c2fb20c06c77844c1e3ee0659a" }, { "contractName": "L1Messenger", "bytecodePath": "zkout/L1Messenger.sol/L1Messenger.json", "sourceCodePath": "contracts-preprocessed/L1Messenger.sol", - "bytecodeHash": "0x01000263345d82f95b6533501ee84340770418287866931d64899423815527f8", + "bytecodeHash": "0x0100026320ad1a050ca08117bb57a06684839b3ab3f3095e17deb1ebeb53d4ac", "sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a" }, { "contractName": "L2BaseToken", "bytecodePath": "zkout/L2BaseToken.sol/L2BaseToken.json", "sourceCodePath": "contracts-preprocessed/L2BaseToken.sol", - "bytecodeHash": "0x010000dbc44fbd6fd01e930a4cbbb59a17b285bd86fc5dbe11f59d1f375f6286", + "bytecodeHash": "0x010000db58a5798e8cf03299e84c32288bd535f03140112d8461b84ec164887a", "sourceCodeHash": "0xdea518b1ea16718b0f0ec6155b227a8bc8f51374a9eebf7bc17cfe84433df740" }, { "contractName": "MsgValueSimulator", "bytecodePath": "zkout/MsgValueSimulator.sol/MsgValueSimulator.json", "sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol", - "bytecodeHash": "0x010000594d78e2e2a0f0fa224c8ba6b3fd8ab8b283bff7420c1b565fe8a61ee7", + "bytecodeHash": "0x0100005964d673fb20cd2c77df6f9aa4c178bd8ffa54eb582505df704b1f3b5b", "sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71" }, { "contractName": "NonceHolder", "bytecodePath": "zkout/NonceHolder.sol/NonceHolder.json", "sourceCodePath": "contracts-preprocessed/NonceHolder.sol", - "bytecodeHash": "0x010000cf17e28b461edeaf764b45bd824cf6b1a653478624bfa361c813a61b5d", + "bytecodeHash": "0x010000cfa9aff9356b0ef66e9ca32df21ae4bcbb2a8d03d3acf74e2d060a3028", "sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc" }, { "contractName": "PubdataChunkPublisher", "bytecodePath": "zkout/PubdataChunkPublisher.sol/PubdataChunkPublisher.json", "sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol", - "bytecodeHash": "0x01000041dab57304eb3d41b96948d580eb388f303bdf058c15b71afcef0ffac0", + "bytecodeHash": "0x010000419856be032b7143f70782d129e260d6e99e6bbe7c4787884ccd949ce9", "sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e" }, { "contractName": "SystemContext", "bytecodePath": "zkout/SystemContext.sol/SystemContext.json", "sourceCodePath": "contracts-preprocessed/SystemContext.sol", - "bytecodeHash": "0x010001c54c88a8fb2427458c7b4caddc0c7927e396a60a5e690408d36a25eceb", - "sourceCodeHash": "0xe2f6eb015d260aafe9405b28ef3ec27921add4de7f329b7ef61e0aa6c9365e29" + "bytecodeHash": "0x010001a5305c969f525ba5afc3c7496c520d77ca71bdebc9c3b8e71c7a0d3364", + "sourceCodeHash": "0xaf04a52c660f48de04c29b6c88632b4e002e94f58e0f8de034fd73959671c984" }, { "contractName": "EventWriter", @@ -122,8 +122,8 @@ "contractName": "EvmEmulator", "bytecodePath": "zkout/EvmEmulator.yul/contracts-preprocessed/EvmEmulator.yul.json", "sourceCodePath": "contracts-preprocessed/EvmEmulator.yul", - "bytecodeHash": "0x01000c0750cd078b79c3bcf0ac3074e75a6824fe05e0e563e6df442feb879847", - "sourceCodeHash": "0x86296ecb81fc9edf5aac32613dfd645b538535e264e02a12ec7cdc751018de5d" + "bytecodeHash": "0x01000bef3afffa6dcca82a514f5f388101dd3498e9117be2073975d8ae791970", + "sourceCodeHash": "0x7cad60f966f85be729468ca5f3500ffd4a4b2d0ef6df5ca0656ac7f46c0d2402" }, { "contractName": "EvmGasManager", diff --git a/system-contracts/contracts/Constants.sol b/system-contracts/contracts/Constants.sol index 36309b111..fbaabc091 100644 --- a/system-contracts/contracts/Constants.sol +++ b/system-contracts/contracts/Constants.sol @@ -167,4 +167,6 @@ uint256 constant MAX_NUMBER_OF_BLOBS = 6; /// @dev Marker of EraVM bytecode uint8 constant ERA_VM_BYTECODE_FLAG = 1; /// @dev Marker of EVM bytecode -uint8 constant EVM_BYTECODE_FLAG = 2; \ No newline at end of file +uint8 constant EVM_BYTECODE_FLAG = 2; + +address constant SERVICE_CALL_PSEUDO_CALLER = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; \ No newline at end of file diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index 3b36ed732..d00b50515 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -4,13 +4,13 @@ pragma solidity 0.8.24; 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, SYSTEM_CONTEXT_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, SERVICE_CALL_PSEUDO_CALLER} from "./Constants.sol"; import {Utils} from "./libraries/Utils.sol"; import {EfficientCall} from "./libraries/EfficientCall.sol"; import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; import {SystemContractBase} from "./abstract/SystemContractBase.sol"; -import {Unauthorized, InvalidAllowedBytecodeTypesMode, InvalidNonceOrderingChange, ValueMismatch, EmptyBytes32, EVMEmulationNotSupported, NotAllowedToDeployInKernelSpace, HashIsNonZero, NonEmptyAccount, UnknownCodeHash, NonEmptyMsgValue} from "./SystemContractErrors.sol"; +import {Unauthorized, InvalidNonceOrderingChange, ValueMismatch, EmptyBytes32, EVMEmulationNotSupported, NotAllowedToDeployInKernelSpace, HashIsNonZero, NonEmptyAccount, UnknownCodeHash, NonEmptyMsgValue} from "./SystemContractErrors.sol"; /** * @author Matter Labs @@ -360,23 +360,16 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { /// @notice Changes what types of bytecodes are allowed to be deployed on the chain. Can be used only during upgrades. /// @param newAllowedBytecodeTypes The new allowed bytecode types mode. - function setAllowedBytecodeTypesToDeploy(uint256 newAllowedBytecodeTypes) external { + function setAllowedBytecodeTypesToDeploy(AllowedBytecodeTypes newAllowedBytecodeTypes) external { if ( msg.sender != FORCE_DEPLOYER && msg.sender != address(COMPLEX_UPGRADER_CONTRACT) && - msg.sender != address(SYSTEM_CONTEXT_CONTRACT) + msg.sender != SERVICE_CALL_PSEUDO_CALLER ) { revert Unauthorized(msg.sender); } - if ( - newAllowedBytecodeTypes != uint256(AllowedBytecodeTypes.EraVm) && - newAllowedBytecodeTypes != uint256(AllowedBytecodeTypes.EraVmAndEVM) - ) { - revert InvalidAllowedBytecodeTypesMode(); - } - - if (uint256(_getAllowedBytecodeTypesMode()) != newAllowedBytecodeTypes) { + if (_getAllowedBytecodeTypesMode() != newAllowedBytecodeTypes) { assembly { sstore(ALLOWED_BYTECODE_TYPES_MODE_SLOT, newAllowedBytecodeTypes) } diff --git a/system-contracts/contracts/SystemContext.sol b/system-contracts/contracts/SystemContext.sol index 10eef6901..2ce75419d 100644 --- a/system-contracts/contracts/SystemContext.sol +++ b/system-contracts/contracts/SystemContext.sol @@ -8,7 +8,7 @@ import {ISystemContext} from "./interfaces/ISystemContext.sol"; import {SystemContractBase} from "./abstract/SystemContractBase.sol"; import {ISystemContextDeprecated} from "./interfaces/ISystemContextDeprecated.sol"; import {SystemContractHelper} from "./libraries/SystemContractHelper.sol"; -import {BOOTLOADER_FORMAL_ADDRESS, DEPLOYER_SYSTEM_CONTRACT, SystemLogKey} from "./Constants.sol"; +import {BOOTLOADER_FORMAL_ADDRESS, SystemLogKey} from "./Constants.sol"; /** * @author Matter Labs @@ -90,17 +90,6 @@ contract SystemContext is ISystemContext, ISystemContextDeprecated, SystemContra chainId = _newChainId; } - /// @notice Set the chain configuration. - /// @param _newChainId The chainId - /// @param _newAllowedBytecodeTypes The new allowed bytecode types mode. - function setChainConfiguration( - uint256 _newChainId, - uint256 _newAllowedBytecodeTypes - ) external onlyCallFromForceDeployer { - chainId = _newChainId; - DEPLOYER_SYSTEM_CONTRACT.setAllowedBytecodeTypesToDeploy(_newAllowedBytecodeTypes); - } - /// @notice Number of current transaction in block. uint16 public txNumberInBlock; diff --git a/system-contracts/contracts/SystemContractErrors.sol b/system-contracts/contracts/SystemContractErrors.sol index 3f0f8c257..2255fafc1 100644 --- a/system-contracts/contracts/SystemContractErrors.sol +++ b/system-contracts/contracts/SystemContractErrors.sol @@ -54,8 +54,6 @@ error IndexSizeError(); error InsufficientFunds(uint256 required, uint256 actual); // 0x1c26714c error InsufficientGas(); -// 0x8322ca79 -error InvalidAllowedBytecodeTypesMode(); // 0xae962d4e error InvalidCall(); // 0x6a84bc39 diff --git a/system-contracts/contracts/interfaces/IContractDeployer.sol b/system-contracts/contracts/interfaces/IContractDeployer.sol index 83bf2392e..fd0d8dec1 100644 --- a/system-contracts/contracts/interfaces/IContractDeployer.sol +++ b/system-contracts/contracts/interfaces/IContractDeployer.sol @@ -112,7 +112,7 @@ interface IContractDeployer { /// @notice Returns keccak of EVM bytecode at address if it is an EVM contract. Returns bytes32(0) if it isn't a EVM contract. function evmCodeHash(address) external view returns (bytes32); - /// @notice Changes what types of bytecodes are allowed to be deployed on the chain. Can be used only during upgrades. + /// @notice Changes what types of bytecodes are allowed to be deployed on the chain. /// @param newAllowedBytecodeTypes The new allowed bytecode types mode. - function setAllowedBytecodeTypesToDeploy(uint256 newAllowedBytecodeTypes) external; + function setAllowedBytecodeTypesToDeploy(AllowedBytecodeTypes newAllowedBytecodeTypes) external; } From e7aa3a96a0129d71ac58ffd9fd7ad876b69dc209 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Wed, 18 Dec 2024 12:39:12 +0100 Subject: [PATCH 180/183] fix(EVM): Simplify and optimize out-of-bounds truncation in `CODECOPY` (#1156) --- system-contracts/contracts/EvmEmulator.yul | 18 ++++++++---------- .../evm-emulator/EvmEmulatorLoop.template.yul | 9 ++++----- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index ea8b65d34..feefd03f9 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1749,7 +1749,6 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0x39 { // OP_CODECOPY - evmGasLeft := chargeGas(evmGasLeft, 3) let dstOffset, sourceOffset, len @@ -1774,14 +1773,14 @@ object "EvmEmulator" { sourceOffset := add(sourceOffset, BYTECODE_OFFSET()) - if gt(sourceOffset, MEM_LEN_OFFSET()) { - sourceOffset := MEM_LEN_OFFSET() + if gt(sourceOffset, bytecodeEndOffset) { + sourceOffset := bytecodeEndOffset } // Check bytecode out-of-bounds access let truncatedLen := len - if gt(add(sourceOffset, len), MEM_LEN_OFFSET()) { - truncatedLen := sub(MEM_LEN_OFFSET(), sourceOffset) // truncate + if gt(add(sourceOffset, len), bytecodeEndOffset) { + truncatedLen := sub(bytecodeEndOffset, sourceOffset) // truncate $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, truncatedLen), sub(len, truncatedLen)) // pad with zeroes any out-of-bounds } @@ -4889,7 +4888,6 @@ object "EvmEmulator" { ip := add(ip, 1) } case 0x39 { // OP_CODECOPY - evmGasLeft := chargeGas(evmGasLeft, 3) let dstOffset, sourceOffset, len @@ -4914,14 +4912,14 @@ object "EvmEmulator" { sourceOffset := add(sourceOffset, BYTECODE_OFFSET()) - if gt(sourceOffset, MEM_LEN_OFFSET()) { - sourceOffset := MEM_LEN_OFFSET() + if gt(sourceOffset, bytecodeEndOffset) { + sourceOffset := bytecodeEndOffset } // Check bytecode out-of-bounds access let truncatedLen := len - if gt(add(sourceOffset, len), MEM_LEN_OFFSET()) { - truncatedLen := sub(MEM_LEN_OFFSET(), sourceOffset) // truncate + if gt(add(sourceOffset, len), bytecodeEndOffset) { + truncatedLen := sub(bytecodeEndOffset, sourceOffset) // truncate $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, truncatedLen), sub(len, truncatedLen)) // pad with zeroes any out-of-bounds } diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index b5d956b44..023b6a747 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -407,7 +407,6 @@ for { } true { } { ip := add(ip, 1) } case 0x39 { // OP_CODECOPY - evmGasLeft := chargeGas(evmGasLeft, 3) let dstOffset, sourceOffset, len @@ -432,14 +431,14 @@ for { } true { } { sourceOffset := add(sourceOffset, BYTECODE_OFFSET()) - if gt(sourceOffset, MEM_LEN_OFFSET()) { - sourceOffset := MEM_LEN_OFFSET() + if gt(sourceOffset, bytecodeEndOffset) { + sourceOffset := bytecodeEndOffset } // Check bytecode out-of-bounds access let truncatedLen := len - if gt(add(sourceOffset, len), MEM_LEN_OFFSET()) { - truncatedLen := sub(MEM_LEN_OFFSET(), sourceOffset) // truncate + if gt(add(sourceOffset, len), bytecodeEndOffset) { + truncatedLen := sub(bytecodeEndOffset, sourceOffset) // truncate $llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, truncatedLen), sub(len, truncatedLen)) // pad with zeroes any out-of-bounds } From c396c03ec85ef18bffce73776789e6812a7059b4 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Thu, 19 Dec 2024 10:54:12 +0100 Subject: [PATCH 181/183] fix(EVM): Store unpadded EVM bytecode length in versioned bytecode hash (updated) (#1157) --- .../contracts/ContractDeployer.sol | 22 ++- system-contracts/contracts/EvmEmulator.yul | 137 +++++++----------- .../contracts/KnownCodesStorage.sol | 4 +- .../contracts/SystemContractErrors.sol | 3 +- .../interfaces/IKnownCodesStorage.sol | 2 +- .../contracts/libraries/Utils.sol | 22 ++- .../contracts/precompiles/CodeOracle.yul | 19 ++- .../evm-emulator/EvmEmulator.template.yul | 13 +- .../EvmEmulatorFunctions.template.yul | 48 ++---- .../evm-emulator/EvmEmulatorLoop.template.yul | 14 +- .../test/KnownCodesStorage.spec.ts | 11 +- 11 files changed, 142 insertions(+), 153 deletions(-) diff --git a/system-contracts/contracts/ContractDeployer.sol b/system-contracts/contracts/ContractDeployer.sol index d00b50515..f909e3fb0 100644 --- a/system-contracts/contracts/ContractDeployer.sol +++ b/system-contracts/contracts/ContractDeployer.sol @@ -250,7 +250,12 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { address _newAddress, bytes calldata _initCode ) external payable onlySystemCallFromEvmEmulator returns (uint256, address) { - uint256 constructorReturnEvmGas = _performDeployOnAddressEVM(msg.sender, _newAddress, AccountAbstractionVersion.None, _initCode); + uint256 constructorReturnEvmGas = _performDeployOnAddressEVM( + msg.sender, + _newAddress, + AccountAbstractionVersion.None, + _initCode + ); return (constructorReturnEvmGas, _newAddress); } @@ -584,25 +589,26 @@ contract ContractDeployer is IContractDeployer, SystemContractBase { _isSystem: false }); - // Returned data bytes have structure: bytecode.constructorReturnEvmGas + uint256 evmBytecodeLen; + // Returned data bytes have structure: paddedBytecode.evmBytecodeLen.constructorReturnEvmGas assembly { let dataLen := mload(paddedBytecode) + evmBytecodeLen := mload(add(paddedBytecode, sub(dataLen, 0x20))) constructorReturnEvmGas := mload(add(paddedBytecode, dataLen)) - mstore(paddedBytecode, sub(dataLen, 0x20)) // shrink paddedBytecode + mstore(paddedBytecode, sub(dataLen, 0x40)) // shrink paddedBytecode } - bytes32 versionedCodeHash = KNOWN_CODE_STORAGE_CONTRACT.publishEVMBytecode(paddedBytecode); - ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.storeAccountConstructedCodeHash(_newAddress, versionedCodeHash); + bytes32 versionedBytecodeHash = KNOWN_CODE_STORAGE_CONTRACT.publishEVMBytecode(evmBytecodeLen, paddedBytecode); + ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT.storeAccountConstructedCodeHash(_newAddress, versionedBytecodeHash); bytes32 evmBytecodeHash; assembly { - let bytecodeLen := mload(add(paddedBytecode, 0x20)) - evmBytecodeHash := keccak256(add(paddedBytecode, 0x40), bytecodeLen) + evmBytecodeHash := keccak256(add(paddedBytecode, 0x20), evmBytecodeLen) } _setEvmCodeHash(_newAddress, evmBytecodeHash); - emit ContractDeployed(_sender, versionedCodeHash, _newAddress); + emit ContractDeployed(_sender, versionedBytecodeHash, _newAddress); } function _setEvmCodeHash(address _address, bytes32 _hash) internal { diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index feefd03f9..9c6e62fef 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -21,16 +21,14 @@ object "EvmEmulator" { copyActivePtrData(BYTECODE_OFFSET(), 0, size) } - function padBytecode(offset, len) -> blobOffset, blobLen { - blobOffset := sub(offset, 32) + function padBytecode(offset, len) -> blobLen { let trueLastByte := add(offset, len) - mstore(blobOffset, len) // clearing out additional bytes mstore(trueLastByte, 0) mstore(add(trueLastByte, 32), 0) - blobLen := add(len, 32) + blobLen := len if iszero(eq(mod(blobLen, 32), 0)) { blobLen := add(blobLen, sub(32, mod(blobLen, 32))) @@ -411,61 +409,41 @@ object "EvmEmulator" { // Basically performs an extcodecopy, while returning the length of the copied bytecode. function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { - let codeHash := getRawCodeHash(addr) - mstore(0, codeHash) + let rawCodeHash := getRawCodeHash(addr) + mstore(0, rawCodeHash) let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) // it fails if we don't have any code deployed at this address if success { - returndatacopy(0, 0, 32) - // The first word of returndata is the true length of the bytecode - let codeLen := mload(0) + // The length of the bytecode is encoded in versioned bytecode hash + let codeLen := and(shr(224, rawCodeHash), 0xffff) + + if eq(shr(248, rawCodeHash), 1) { + // For native zkVM contracts length encoded in words, not bytes + codeLen := shl(5, codeLen) // * 32 + } if gt(len, codeLen) { len := codeLen } - let shiftedSrcOffset := add(32, srcOffset) // first 32 bytes is length - let _returndatasize := returndatasize() - if gt(shiftedSrcOffset, _returndatasize) { - shiftedSrcOffset := _returndatasize + if gt(srcOffset, _returndatasize) { + srcOffset := _returndatasize } - if gt(add(len, shiftedSrcOffset), _returndatasize) { - len := sub(_returndatasize, shiftedSrcOffset) + if gt(add(len, srcOffset), _returndatasize) { + len := sub(_returndatasize, srcOffset) } if len { - returndatacopy(dstOffset, shiftedSrcOffset, len) + returndatacopy(dstOffset, srcOffset, len) } copiedLen := len } } - // Returns the length of the EVM bytecode. - function fetchDeployedEvmCodeLen(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 getMax(a, b) -> max { max := b if gt(a, b) { @@ -1809,9 +1787,17 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - switch isEvmContract(addr) - case 0 { stackHead := extcodesize(addr) } - default { stackHead := fetchDeployedEvmCodeLen(addr) } + let rawCodeHash := getRawCodeHash(addr) + switch shr(248, rawCodeHash) + case 1 { + stackHead := extcodesize(addr) + } + case 2 { + stackHead := and(shr(224, rawCodeHash), 0xffff) + } + default { + stackHead := 0 + } ip := add(ip, 1) } @@ -3175,11 +3161,12 @@ object "EvmEmulator" { gasToReturn := validateBytecodeAndChargeGas(offset, len, gasToReturn) - offset, len := padBytecode(offset, len) + let blobLen := padBytecode(offset, len) - mstore(add(offset, len), gasToReturn) + mstore(add(offset, blobLen), len) + mstore(add(offset, add(32, blobLen)), gasToReturn) - verbatim_2i_0o("return_deployed", offset, add(len, 32)) + verbatim_2i_0o("return_deployed", offset, add(blobLen, 64)) } object "EvmEmulator_deployed" { code { @@ -3550,61 +3537,41 @@ object "EvmEmulator" { // Basically performs an extcodecopy, while returning the length of the copied bytecode. function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { - let codeHash := getRawCodeHash(addr) - mstore(0, codeHash) + let rawCodeHash := getRawCodeHash(addr) + mstore(0, rawCodeHash) let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) // it fails if we don't have any code deployed at this address if success { - returndatacopy(0, 0, 32) - // The first word of returndata is the true length of the bytecode - let codeLen := mload(0) + // The length of the bytecode is encoded in versioned bytecode hash + let codeLen := and(shr(224, rawCodeHash), 0xffff) + + if eq(shr(248, rawCodeHash), 1) { + // For native zkVM contracts length encoded in words, not bytes + codeLen := shl(5, codeLen) // * 32 + } if gt(len, codeLen) { len := codeLen } - let shiftedSrcOffset := add(32, srcOffset) // first 32 bytes is length - let _returndatasize := returndatasize() - if gt(shiftedSrcOffset, _returndatasize) { - shiftedSrcOffset := _returndatasize + if gt(srcOffset, _returndatasize) { + srcOffset := _returndatasize } - if gt(add(len, shiftedSrcOffset), _returndatasize) { - len := sub(_returndatasize, shiftedSrcOffset) + if gt(add(len, srcOffset), _returndatasize) { + len := sub(_returndatasize, srcOffset) } if len { - returndatacopy(dstOffset, shiftedSrcOffset, len) + returndatacopy(dstOffset, srcOffset, len) } copiedLen := len } } - // Returns the length of the EVM bytecode. - function fetchDeployedEvmCodeLen(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 getMax(a, b) -> max { max := b if gt(a, b) { @@ -4948,9 +4915,17 @@ object "EvmEmulator" { evmGasLeft := chargeGas(evmGasLeft, 2500) } - switch isEvmContract(addr) - case 0 { stackHead := extcodesize(addr) } - default { stackHead := fetchDeployedEvmCodeLen(addr) } + let rawCodeHash := getRawCodeHash(addr) + switch shr(248, rawCodeHash) + case 1 { + stackHead := extcodesize(addr) + } + case 2 { + stackHead := and(shr(224, rawCodeHash), 0xffff) + } + default { + stackHead := 0 + } ip := add(ip, 1) } diff --git a/system-contracts/contracts/KnownCodesStorage.sol b/system-contracts/contracts/KnownCodesStorage.sol index 1f3755e4e..463105a64 100644 --- a/system-contracts/contracts/KnownCodesStorage.sol +++ b/system-contracts/contracts/KnownCodesStorage.sol @@ -87,11 +87,13 @@ contract KnownCodesStorage is IKnownCodesStorage, SystemContractBase { /// @notice The method used by ContractDeployer to publish EVM bytecode /// @dev Bytecode should be padded by EraVM rules + /// @param paddedBytecode The length of EVM bytecode in bytes /// @param paddedBytecode The bytecode to be published function publishEVMBytecode( + uint256 evmBytecodeLen, bytes calldata paddedBytecode ) external payable onlyCallFrom(address(DEPLOYER_SYSTEM_CONTRACT)) returns (bytes32) { - bytes32 vesionedBytecodeHash = Utils.hashEVMBytecode(paddedBytecode); + bytes32 vesionedBytecodeHash = Utils.hashEVMBytecode(evmBytecodeLen, paddedBytecode); if (getMarker(vesionedBytecodeHash) == 0) { L1_MESSENGER_CONTRACT.sendToL1(paddedBytecode); diff --git a/system-contracts/contracts/SystemContractErrors.sol b/system-contracts/contracts/SystemContractErrors.sol index 2255fafc1..2ba8eed26 100644 --- a/system-contracts/contracts/SystemContractErrors.sol +++ b/system-contracts/contracts/SystemContractErrors.sol @@ -143,5 +143,6 @@ enum BytecodeError { Length, WordsMustBeOdd, DictionaryLength, - EvmBytecodeLength + EvmBytecodeLength, + EvmBytecodeLengthTooBig } diff --git a/system-contracts/contracts/interfaces/IKnownCodesStorage.sol b/system-contracts/contracts/interfaces/IKnownCodesStorage.sol index 984f203aa..fc019be93 100644 --- a/system-contracts/contracts/interfaces/IKnownCodesStorage.sol +++ b/system-contracts/contracts/interfaces/IKnownCodesStorage.sol @@ -17,5 +17,5 @@ interface IKnownCodesStorage { function getMarker(bytes32 _hash) external view returns (uint256); - function publishEVMBytecode(bytes calldata bytecode) external payable returns (bytes32); + function publishEVMBytecode(uint256 evmBytecodeLen, bytes calldata bytecode) external payable returns (bytes32); } diff --git a/system-contracts/contracts/libraries/Utils.sol b/system-contracts/contracts/libraries/Utils.sol index bc423c885..94a615da0 100644 --- a/system-contracts/contracts/libraries/Utils.sol +++ b/system-contracts/contracts/libraries/Utils.sol @@ -138,35 +138,43 @@ library Utils { uint256 internal constant MAX_EVM_BYTECODE_LENGTH = (2 ** 16) - 1; /// @notice Validate the bytecode format and calculate its hash. - /// @param _bytecode The EVM bytecode to hash. + /// @param _evmBytecodeLen The length of original EVM bytecode in bytes + /// @param _paddedBytecode The padded EVM bytecode to hash. /// @return hashedEVMBytecode The 32-byte hash of the EVM bytecode. /// Note: The function reverts the execution if the bytecode has non expected format: /// - Bytecode bytes length is not a multiple of 32 /// - Bytecode bytes length is greater than 2^16 - 1 bytes /// - Bytecode words length is not odd - function hashEVMBytecode(bytes calldata _bytecode) internal view returns (bytes32 hashedEVMBytecode) { + function hashEVMBytecode( + uint256 _evmBytecodeLen, + bytes calldata _paddedBytecode + ) internal view returns (bytes32 hashedEVMBytecode) { // Note that the length of the bytecode must be provided in 32-byte words. - if (_bytecode.length % 32 != 0) { + if (_paddedBytecode.length % 32 != 0) { revert MalformedBytecode(BytecodeError.Length); } - if (_bytecode.length > MAX_EVM_BYTECODE_LENGTH) { + if (_evmBytecodeLen > _paddedBytecode.length) { revert MalformedBytecode(BytecodeError.EvmBytecodeLength); } - uint256 lengthInWords = _bytecode.length / 32; + if (_evmBytecodeLen > MAX_EVM_BYTECODE_LENGTH) { + revert MalformedBytecode(BytecodeError.EvmBytecodeLengthTooBig); + } + + uint256 lengthInWords = _paddedBytecode.length / 32; // bytecode length in words must be odd if (lengthInWords % 2 == 0) { revert MalformedBytecode(BytecodeError.WordsMustBeOdd); } hashedEVMBytecode = - EfficientCall.sha(_bytecode) & + EfficientCall.sha(_paddedBytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // Setting the version of the hash hashedEVMBytecode = (hashedEVMBytecode | bytes32(uint256(EVM_BYTECODE_FLAG) << 248)); - hashedEVMBytecode = hashedEVMBytecode | bytes32(_bytecode.length << 224); + hashedEVMBytecode = hashedEVMBytecode | bytes32(_evmBytecodeLen << 224); } /// @notice Calculates the address of a deployed contract via create2 on the EVM diff --git a/system-contracts/contracts/precompiles/CodeOracle.yul b/system-contracts/contracts/precompiles/CodeOracle.yul index cb12af19f..87145d3be 100644 --- a/system-contracts/contracts/precompiles/CodeOracle.yul +++ b/system-contracts/contracts/precompiles/CodeOracle.yul @@ -111,6 +111,19 @@ object "CodeOracle" { return(0, lenInBytes) } + function paddedBytecodeLen(len) -> blobLen { + blobLen := len + + 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) + } + } + //////////////////////////////////////////////////////////////// // FALLBACK //////////////////////////////////////////////////////////////// @@ -147,12 +160,10 @@ object "CodeOracle" { 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) + let paddedLengthInBytes := paddedBytecodeLen(lengthInBytes) - // It is assumed that the `lengthInBytes` is divisible by 32. - decommit(versionedCodeHash, div(lengthInBytes, 32)) + decommit(versionedCodeHash, div(paddedLengthInBytes, 32)) } default { // Unsupported diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index 247cfd786..8e1a4b813 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -21,16 +21,14 @@ object "EvmEmulator" { copyActivePtrData(BYTECODE_OFFSET(), 0, size) } - function padBytecode(offset, len) -> blobOffset, blobLen { - blobOffset := sub(offset, 32) + function padBytecode(offset, len) -> blobLen { let trueLastByte := add(offset, len) - mstore(blobOffset, len) // clearing out additional bytes mstore(trueLastByte, 0) mstore(add(trueLastByte, 32), 0) - blobLen := add(len, 32) + blobLen := len if iszero(eq(mod(blobLen, 32), 0)) { blobLen := add(blobLen, sub(32, mod(blobLen, 32))) @@ -98,11 +96,12 @@ object "EvmEmulator" { gasToReturn := validateBytecodeAndChargeGas(offset, len, gasToReturn) - offset, len := padBytecode(offset, len) + let blobLen := padBytecode(offset, len) - mstore(add(offset, len), gasToReturn) + mstore(add(offset, blobLen), len) + mstore(add(offset, add(32, blobLen)), gasToReturn) - verbatim_2i_0o("return_deployed", offset, add(len, 32)) + verbatim_2i_0o("return_deployed", offset, add(blobLen, 64)) } object "EvmEmulator_deployed" { code { diff --git a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul index 50089c79d..61feb9235 100644 --- a/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul @@ -349,61 +349,41 @@ function isHashOfConstructedEvmContract(rawCodeHash) -> isConstructedEVM { // Basically performs an extcodecopy, while returning the length of the copied bytecode. function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen { - let codeHash := getRawCodeHash(addr) - mstore(0, codeHash) + let rawCodeHash := getRawCodeHash(addr) + mstore(0, rawCodeHash) let success := staticcall(gas(), CODE_ORACLE_SYSTEM_CONTRACT(), 0, 32, 0, 0) // it fails if we don't have any code deployed at this address if success { - returndatacopy(0, 0, 32) - // The first word of returndata is the true length of the bytecode - let codeLen := mload(0) + // The length of the bytecode is encoded in versioned bytecode hash + let codeLen := and(shr(224, rawCodeHash), 0xffff) + + if eq(shr(248, rawCodeHash), 1) { + // For native zkVM contracts length encoded in words, not bytes + codeLen := shl(5, codeLen) // * 32 + } if gt(len, codeLen) { len := codeLen } - let shiftedSrcOffset := add(32, srcOffset) // first 32 bytes is length - let _returndatasize := returndatasize() - if gt(shiftedSrcOffset, _returndatasize) { - shiftedSrcOffset := _returndatasize + if gt(srcOffset, _returndatasize) { + srcOffset := _returndatasize } - if gt(add(len, shiftedSrcOffset), _returndatasize) { - len := sub(_returndatasize, shiftedSrcOffset) + if gt(add(len, srcOffset), _returndatasize) { + len := sub(_returndatasize, srcOffset) } if len { - returndatacopy(dstOffset, shiftedSrcOffset, len) + returndatacopy(dstOffset, srcOffset, len) } copiedLen := len } } -// Returns the length of the EVM bytecode. -function fetchDeployedEvmCodeLen(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 getMax(a, b) -> max { max := b if gt(a, b) { diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 023b6a747..883941a17 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -467,9 +467,17 @@ for { } true { } { evmGasLeft := chargeGas(evmGasLeft, 2500) } - switch isEvmContract(addr) - case 0 { stackHead := extcodesize(addr) } - default { stackHead := fetchDeployedEvmCodeLen(addr) } + let rawCodeHash := getRawCodeHash(addr) + switch shr(248, rawCodeHash) + case 1 { + stackHead := extcodesize(addr) + } + case 2 { + stackHead := and(shr(224, rawCodeHash), 0xffff) + } + default { + stackHead := 0 + } ip := add(ip, 1) } diff --git a/system-contracts/test/KnownCodesStorage.spec.ts b/system-contracts/test/KnownCodesStorage.spec.ts index 395249eec..5444c519d 100644 --- a/system-contracts/test/KnownCodesStorage.spec.ts +++ b/system-contracts/test/KnownCodesStorage.spec.ts @@ -96,7 +96,7 @@ describe("KnownCodesStorage tests", function () { }); it("non-deployer failed to call", async () => { - await expect(knownCodesStorage.publishEVMBytecode("0x00")).to.be.revertedWithCustomError( + await expect(knownCodesStorage.publishEVMBytecode(1, "0x00")).to.be.revertedWithCustomError( knownCodesStorage, "Unauthorized" ); @@ -104,15 +104,14 @@ describe("KnownCodesStorage tests", function () { it("bytecode with even length failed to publish", async () => { await expect( - knownCodesStorage.connect(deployerAccount).publishEVMBytecode(InvalidBytecode) + knownCodesStorage.connect(deployerAccount).publishEVMBytecode(64, InvalidBytecode) ).to.be.revertedWithCustomError(knownCodesStorage, "MalformedBytecode"); }); it("invalid length bytecode failed to call", async () => { - await expect(knownCodesStorage.connect(deployerAccount).publishEVMBytecode("0x00")).to.be.revertedWithCustomError( - knownCodesStorage, - "MalformedBytecode" - ); + await expect( + knownCodesStorage.connect(deployerAccount).publishEVMBytecode(1, "0x00") + ).to.be.revertedWithCustomError(knownCodesStorage, "MalformedBytecode"); }); }); From 0419d3e1ab3ba2715ce87eb86fa60145cd7a2de8 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 20 Dec 2024 13:39:44 +0100 Subject: [PATCH 182/183] fix(EVM): Add overflow checks in `JUMP` and `JUMPI` opcodes (#1159) --- system-contracts/contracts/EvmEmulator.yul | 20 +++++++++++++++++++ .../evm-emulator/EvmEmulatorLoop.template.yul | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 9c6e62fef..6653c623c 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -2122,6 +2122,11 @@ object "EvmEmulator" { let counter counter, sp, stackHead := popStackItem(sp, stackHead) + // Counter certainly can't be bigger than uint64. + if gt(counter, MAX_UINT64()) { + panic() + } + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST @@ -2147,6 +2152,11 @@ object "EvmEmulator" { continue } + // Counter certainly can't be bigger than uint64. + if gt(counter, MAX_UINT64()) { + panic() + } + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST @@ -5250,6 +5260,11 @@ object "EvmEmulator" { let counter counter, sp, stackHead := popStackItem(sp, stackHead) + // Counter certainly can't be bigger than uint64. + if gt(counter, MAX_UINT64()) { + panic() + } + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST @@ -5275,6 +5290,11 @@ object "EvmEmulator" { continue } + // Counter certainly can't be bigger than uint64. + if gt(counter, MAX_UINT64()) { + panic() + } + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index 883941a17..cd9d5a2c5 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -802,6 +802,11 @@ for { } true { } { let counter counter, sp, stackHead := popStackItem(sp, stackHead) + // Counter certainly can't be bigger than uint64. + if gt(counter, MAX_UINT64()) { + panic() + } + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST @@ -827,6 +832,11 @@ for { } true { } { continue } + // Counter certainly can't be bigger than uint64. + if gt(counter, MAX_UINT64()) { + panic() + } + ip := add(BYTECODE_OFFSET(), counter) // Check next opcode is JUMPDEST From 684c072d0caea28a1f970d4d7ba98effa374f8c4 Mon Sep 17 00:00:00 2001 From: Vladislav Volosnikov Date: Fri, 20 Dec 2024 14:27:01 +0100 Subject: [PATCH 183/183] fix(EVM): Handle calldata-related opcodes in constructor (#1160) --- system-contracts/contracts/EvmEmulator.yul | 47 +++++++++++++------ .../evm-emulator/EvmEmulator.template.yul | 4 ++ .../evm-emulator/EvmEmulatorLoop.template.yul | 10 ++-- .../ConstructorScope.template.yul | 11 +++++ .../RuntimeScope.template.yul | 14 ++++++ 5 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 system-contracts/evm-emulator/calldata-opcodes/ConstructorScope.template.yul create mode 100644 system-contracts/evm-emulator/calldata-opcodes/RuntimeScope.template.yul diff --git a/system-contracts/contracts/EvmEmulator.yul b/system-contracts/contracts/EvmEmulator.yul index 6653c623c..5b41e6643 100644 --- a/system-contracts/contracts/EvmEmulator.yul +++ b/system-contracts/contracts/EvmEmulator.yul @@ -1309,6 +1309,18 @@ object "EvmEmulator" { } } + function $llvm_AlwaysInline_llvm$_calldatasize() -> size { + size := 0 + } + + function $llvm_AlwaysInline_llvm$_calldatacopy(dstOffset, sourceOffset, truncatedLen) { + $llvm_AlwaysInline_llvm$_memsetToZero(dstOffset, truncatedLen) + } + + function $llvm_AlwaysInline_llvm$_calldataload(calldataOffset) -> res { + res := 0 + } + function simulate( isCallerEVM, evmGasLeft, @@ -1667,18 +1679,14 @@ object "EvmEmulator" { let calldataOffset := accessStackHead(sp, stackHead) - stackHead := 0 - // EraVM will revert if offset + length overflows uint32 - if lt(calldataOffset, UINT32_MAX()) { - stackHead := calldataload(calldataOffset) - } + stackHead := $llvm_AlwaysInline_llvm$_calldataload(calldataOffset) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, calldatasize(), stackHead) + sp, stackHead := pushStackItem(sp, $llvm_AlwaysInline_llvm$_calldatasize(), stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -1713,7 +1721,7 @@ object "EvmEmulator" { } if truncatedLen { - calldatacopy(dstOffset, sourceOffset, truncatedLen) + $llvm_AlwaysInline_llvm$_calldatacopy(dstOffset, sourceOffset, truncatedLen) } ip := add(ip, 1) @@ -4805,18 +4813,14 @@ object "EvmEmulator" { let calldataOffset := accessStackHead(sp, stackHead) - stackHead := 0 - // EraVM will revert if offset + length overflows uint32 - if lt(calldataOffset, UINT32_MAX()) { - stackHead := calldataload(calldataOffset) - } + stackHead := $llvm_AlwaysInline_llvm$_calldataload(calldataOffset) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, calldatasize(), stackHead) + sp, stackHead := pushStackItem(sp, $llvm_AlwaysInline_llvm$_calldatasize(), stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -4851,7 +4855,7 @@ object "EvmEmulator" { } if truncatedLen { - calldatacopy(dstOffset, sourceOffset, truncatedLen) + $llvm_AlwaysInline_llvm$_calldatacopy(dstOffset, sourceOffset, truncatedLen) } ip := add(ip, 1) @@ -6284,6 +6288,21 @@ object "EvmEmulator" { } + function $llvm_AlwaysInline_llvm$_calldatasize() -> size { + size := calldatasize() + } + + function $llvm_AlwaysInline_llvm$_calldatacopy(dstOffset, sourceOffset, truncatedLen) { + calldatacopy(dstOffset, sourceOffset, truncatedLen) + } + + function $llvm_AlwaysInline_llvm$_calldataload(calldataOffset) -> res { + // EraVM will revert if offset + length overflows uint32 + if lt(calldataOffset, UINT32_MAX()) { + res := calldataload(calldataOffset) + } + } + if eq(isCallerEVM, 1) { // Includes gas returnOffset := sub(returnOffset, 32) diff --git a/system-contracts/evm-emulator/EvmEmulator.template.yul b/system-contracts/evm-emulator/EvmEmulator.template.yul index 8e1a4b813..22d188075 100644 --- a/system-contracts/evm-emulator/EvmEmulator.template.yul +++ b/system-contracts/evm-emulator/EvmEmulator.template.yul @@ -60,6 +60,8 @@ object "EvmEmulator" { + + function simulate( isCallerEVM, evmGasLeft, @@ -134,6 +136,8 @@ object "EvmEmulator" { + + if eq(isCallerEVM, 1) { // Includes gas returnOffset := sub(returnOffset, 32) diff --git a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul index cd9d5a2c5..d5056dd19 100644 --- a/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul +++ b/system-contracts/evm-emulator/EvmEmulatorLoop.template.yul @@ -347,18 +347,14 @@ for { } true { } { let calldataOffset := accessStackHead(sp, stackHead) - stackHead := 0 - // EraVM will revert if offset + length overflows uint32 - if lt(calldataOffset, UINT32_MAX()) { - stackHead := calldataload(calldataOffset) - } + stackHead := $llvm_AlwaysInline_llvm$_calldataload(calldataOffset) ip := add(ip, 1) } case 0x36 { // OP_CALLDATASIZE evmGasLeft := chargeGas(evmGasLeft, 2) - sp, stackHead := pushStackItem(sp, calldatasize(), stackHead) + sp, stackHead := pushStackItem(sp, $llvm_AlwaysInline_llvm$_calldatasize(), stackHead) ip := add(ip, 1) } case 0x37 { // OP_CALLDATACOPY @@ -393,7 +389,7 @@ for { } true { } { } if truncatedLen { - calldatacopy(dstOffset, sourceOffset, truncatedLen) + $llvm_AlwaysInline_llvm$_calldatacopy(dstOffset, sourceOffset, truncatedLen) } ip := add(ip, 1) diff --git a/system-contracts/evm-emulator/calldata-opcodes/ConstructorScope.template.yul b/system-contracts/evm-emulator/calldata-opcodes/ConstructorScope.template.yul new file mode 100644 index 000000000..075f4dfaa --- /dev/null +++ b/system-contracts/evm-emulator/calldata-opcodes/ConstructorScope.template.yul @@ -0,0 +1,11 @@ +function $llvm_AlwaysInline_llvm$_calldatasize() -> size { + size := 0 +} + +function $llvm_AlwaysInline_llvm$_calldatacopy(dstOffset, sourceOffset, truncatedLen) { + $llvm_AlwaysInline_llvm$_memsetToZero(dstOffset, truncatedLen) +} + +function $llvm_AlwaysInline_llvm$_calldataload(calldataOffset) -> res { + res := 0 +} \ No newline at end of file diff --git a/system-contracts/evm-emulator/calldata-opcodes/RuntimeScope.template.yul b/system-contracts/evm-emulator/calldata-opcodes/RuntimeScope.template.yul new file mode 100644 index 000000000..51c88e7b5 --- /dev/null +++ b/system-contracts/evm-emulator/calldata-opcodes/RuntimeScope.template.yul @@ -0,0 +1,14 @@ +function $llvm_AlwaysInline_llvm$_calldatasize() -> size { + size := calldatasize() +} + +function $llvm_AlwaysInline_llvm$_calldatacopy(dstOffset, sourceOffset, truncatedLen) { + calldatacopy(dstOffset, sourceOffset, truncatedLen) +} + +function $llvm_AlwaysInline_llvm$_calldataload(calldataOffset) -> res { + // EraVM will revert if offset + length overflows uint32 + if lt(calldataOffset, UINT32_MAX()) { + res := calldataload(calldataOffset) + } +} \ No newline at end of file