From d80af24152c0f43335d665f15d4e606dcd6677f8 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 25 Feb 2021 21:28:03 -0500 Subject: [PATCH 01/39] Remove inaccurate visibility kw --- .../optimistic-ethereum/iOVM/execution/iOVM_SafetyChecker.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyChecker.sol b/contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyChecker.sol index 848e47ddf..91e8465a7 100644 --- a/contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyChecker.sol +++ b/contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyChecker.sol @@ -10,5 +10,5 @@ interface iOVM_SafetyChecker { * Public Functions * ********************/ - function isBytecodeSafe(bytes calldata _bytecode) external pure returns (bool); + function isBytecodeSafe(bytes calldata _bytecode) external returns (bool); } From c897739d6aa2d53b78082f4ec5eaa4febf3cfa8d Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 25 Feb 2021 21:34:26 -0500 Subject: [PATCH 02/39] Add SafetyCache --- .../OVM/execution/OVM_ExecutionManager.sol | 20 ++-- .../OVM/execution/OVM_SafetyCache.sol | 94 +++++++++++++++++++ .../OVM/execution/OVM_SafetyChecker.sol | 2 +- .../iOVM/execution/iOVM_SafetyCache.sol | 16 ++++ 4 files changed, 122 insertions(+), 10 deletions(-) create mode 100644 contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol create mode 100644 contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyCache.sol diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index 021880581..61473d824 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -8,10 +8,12 @@ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; import { Lib_EthUtils } from "../../libraries/utils/Lib_EthUtils.sol"; -/* Interface Imports */ +/* Inherited Interface Imports */ import { iOVM_ExecutionManager } from "../../iOVM/execution/iOVM_ExecutionManager.sol"; + +/* External Interface Imports */ import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol"; -import { iOVM_SafetyChecker } from "../../iOVM/execution/iOVM_SafetyChecker.sol"; +import { iOVM_SafetyCache } from "../../iOVM/execution/iOVM_SafetyCache.sol"; /* Contract Imports */ import { OVM_ECDSAContractAccount } from "../accounts/OVM_ECDSAContractAccount.sol"; @@ -27,7 +29,7 @@ import { OVM_DeployerWhitelist } from "../precompiles/OVM_DeployerWhitelist.sol" * transaction on L2. * For each context-dependent EVM operation the EM has a function which implements a corresponding * OVM operation, which will read state from the State Manager contract. - * The EM relies on the Safety Checker to verify that code deployed to Layer 2 does not contain any + * The EM relies on the Safety Cache and Checker to verify that code deployed to Layer 2 does not contain any * context-dependent operations. * * Compiler used: solc @@ -39,7 +41,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { * External Contract References * ********************************/ - iOVM_SafetyChecker internal ovmSafetyChecker; + iOVM_SafetyCache internal ovmSafetyCache; iOVM_StateManager internal ovmStateManager; @@ -82,7 +84,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { public Lib_AddressResolver(_libAddressManager) { - ovmSafetyChecker = iOVM_SafetyChecker(resolve("OVM_SafetyChecker")); + ovmSafetyCache = iOVM_SafetyCache(resolve("OVM_SafetyCache")); gasMeterConfig = _gasMeterConfig; globalContext = _globalContext; } @@ -806,8 +808,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _revertWithFlag(RevertFlag.CREATE_COLLISION); } - // Check the creation bytecode against the OVM_SafetyChecker. - if (ovmSafetyChecker.isBytecodeSafe(_bytecode) == false) { + // Check the creation bytecode against the Safety Cache and Safety Checker. + if (ovmSafetyCache.checkAndRegisterSafeBytecode(_bytecode) == false) { _revertWithFlag(RevertFlag.UNSAFE_BYTECODE); } @@ -838,7 +840,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // Again simply checking that the deployed code is safe too. Contracts can generate // arbitrary deployment code, so there's no easy way to analyze this beforehand. bytes memory deployedCode = Lib_EthUtils.getCode(ethAddress); - if (ovmSafetyChecker.isBytecodeSafe(deployedCode) == false) { + if (ovmSafetyCache.checkAndRegisterSafeBytecode(deployedCode) == false) { _revertWithFlag(RevertFlag.UNSAFE_BYTECODE); } @@ -868,7 +870,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { } /******************************************** - * Public Functions: Deployment Witelisting * + * Internal Functions: Deployment Witelisting * ********************************************/ /** diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol new file mode 100644 index 000000000..49399a2ea --- /dev/null +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT +pragma solidity >0.5.0 <0.8.0; + +/* Library Imports */ +import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; + +/* External Interface Imports */ +import { iOVM_SafetyCache } from "../../iOVM/execution/iOVM_SafetyCache.sol"; + +/* Inherited Interface Imports */ +import { iOVM_SafetyChecker } from "../../iOVM/execution/iOVM_SafetyChecker.sol"; + +/** + * @title OVM_SafetyCache + * @dev This contract implements a simple registry for caching the hash of any bytecode strings which have + * already been confirmed safe by the Safety Checker. + * + * Compiler used: solc + * Runtime target: EVM + */ +contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { + + + /******************************************* + * Contract Variables: Contract References * + ******************************************/ + + iOVM_SafetyChecker internal ovmSafetyChecker; + + + /**************************************** + * Contract Variables: Internal Storage * + ****************************************/ + + mapping(bytes32 => bool) internal isSafeCodehash; + + + /*************** + * Constructor * + ***************/ + + /** + * @param _libAddressManager Address of the Address Manager. + */ + constructor( + address _libAddressManager + ) + Lib_AddressResolver(_libAddressManager) + { + ovmSafetyChecker = iOVM_SafetyChecker(resolve("OVM_SafetyChecker")); + } + + + /********************** + * External Functions * + *********************/ + + + /** Checks the registry to see if the verified bytecode is registered as safe. If not, calls to the + * SafetyChecker to see. + * @param _code A bytes32 hash of the code + * @return `true` if the bytecode is safe, `false` otherwise. + */ + function checkAndRegisterSafeBytecode( + bytes memory _code + ) + external + returns ( + bool + ) { + bytes32 codehash = keccak256(abi.encode(_code)); + + if(isSafeCodehash[codehash] == true) { + return true; + } else { + return ovmSafetyChecker.isBytecodeSafe(_code); + } + } + + /** Used to check if bytecode has already been recorded as safe. + * @param _codehash A bytes32 hash of the code + */ + function isRegisteredSafeBytecode( + bytes32 _codehash + ) + external + view + returns ( + bool + ) + { + return (isSafeCodehash[_codehash] == true); + } +} diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyChecker.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyChecker.sol index 404b94230..a71067b7f 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyChecker.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyChecker.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >0.5.0 <0.8.0; -/* Interface Imports */ +/* Inherited Interface Imports */ import { iOVM_SafetyChecker } from "../../iOVM/execution/iOVM_SafetyChecker.sol"; /** diff --git a/contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyCache.sol b/contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyCache.sol new file mode 100644 index 000000000..1ef311ef0 --- /dev/null +++ b/contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyCache.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity >0.5.0 <0.8.0; + +/** + * @title iOVM_SafetyCache + */ +interface iOVM_SafetyCache { + + /******************** + * External Functions * + ********************/ + function checkAndRegisterSafeBytecode(bytes memory _code) external returns (bool) + + function isRegisteredSafeBytecode(bytes32 _codehash) external view returns (bool) + +} From 3fc15f8c5796037f68cee1aa5cf378f5ffd7aa01 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 25 Feb 2021 21:39:11 -0500 Subject: [PATCH 03/39] Add the caching part --- .../optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol index 49399a2ea..f1cb62d3f 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol @@ -72,12 +72,15 @@ contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { if(isSafeCodehash[codehash] == true) { return true; + } else if (ovmSafetyChecker.isBytecodeSafe(_code)) { + isSafeCodehash[_code] = true; } else { - return ovmSafetyChecker.isBytecodeSafe(_code); + return false; } + } - /** Used to check if bytecode has already been recorded as safe. + /** A utility function used to check if bytecode has already been recorded as safe. * @param _codehash A bytes32 hash of the code */ function isRegisteredSafeBytecode( From 4ffe1219b4b66885a7c93f6433fae3a793c7d9e0 Mon Sep 17 00:00:00 2001 From: Annie Ke Date: Thu, 25 Feb 2021 13:22:05 -0800 Subject: [PATCH 04/39] [Fix] CI on merge (#251) * [Fix] CI on merge * rename --- .github/workflows/integration.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 338fc60b5..05db2101c 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -30,7 +30,11 @@ jobs: GIT_COMMIT=$(git rev-parse HEAD | head -c 8) REMOTE=${{ github.event.pull_request.head.repo.html_url }} echo "optimism-integration $GIT_COMMIT" - ./docker/build.sh -s deployer -b $GITHUB_HEAD_REF -r $REMOTE + if [ -z $REMOTE ]; then + ./docker/build.sh -s deployer -b $GITHUB_HEAD_REF + else + ./docker/build.sh -s deployer -b $GITHUB_HEAD_REF -r $REMOTE + fi - name: Test run: | From aa350b8778c8b1a3ea98ea0f1e81ab45f133426c Mon Sep 17 00:00:00 2001 From: Kevin Ho Date: Mon, 1 Mar 2021 12:45:52 -0800 Subject: [PATCH 05/39] remove uniswapv2ERC20 interface import (#258) --- .../iOVM/bridge/tokens/iOVM_L2DepositedERC20.sol | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/contracts/optimistic-ethereum/iOVM/bridge/tokens/iOVM_L2DepositedERC20.sol b/contracts/optimistic-ethereum/iOVM/bridge/tokens/iOVM_L2DepositedERC20.sol index 65bb3fe59..6a2314ad4 100644 --- a/contracts/optimistic-ethereum/iOVM/bridge/tokens/iOVM_L2DepositedERC20.sol +++ b/contracts/optimistic-ethereum/iOVM/bridge/tokens/iOVM_L2DepositedERC20.sol @@ -2,13 +2,10 @@ pragma solidity >0.5.0; pragma experimental ABIEncoderV2; -/* Interface Imports */ -import { IUniswapV2ERC20 } from "../../../libraries/standards/IUniswapV2ERC20.sol"; - /** * @title iOVM_L2DepositedERC20 */ -interface iOVM_L2DepositedERC20 is IUniswapV2ERC20 { +interface iOVM_L2DepositedERC20 { /********** * Events * From c788737ba069ddcf55e7e2a651eaeedc397040ac Mon Sep 17 00:00:00 2001 From: ben-chain Date: Mon, 1 Mar 2021 17:17:11 -0800 Subject: [PATCH 06/39] Reset Context on invalid gaslimit (#260) * add reset * add to constructor --- .../optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index 61473d824..f3d4c8782 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -87,6 +87,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ovmSafetyCache = iOVM_SafetyCache(resolve("OVM_SafetyCache")); gasMeterConfig = _gasMeterConfig; globalContext = _globalContext; + _resetContext(); } @@ -185,6 +186,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // Make sure the transaction's gas limit is valid. We don't revert here because we reserve // reverts for INVALID_STATE_ACCESS. if (_isValidGasLimit(_transaction.gasLimit, _transaction.l1QueueOrigin) == false) { + _resetContext(); return; } From cd408319eb4f940648d3341f4fe7b0333d5742a5 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 25 Feb 2021 21:34:26 -0500 Subject: [PATCH 07/39] Add SafetyCache --- .../optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol index f1cb62d3f..49399a2ea 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol @@ -72,15 +72,12 @@ contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { if(isSafeCodehash[codehash] == true) { return true; - } else if (ovmSafetyChecker.isBytecodeSafe(_code)) { - isSafeCodehash[_code] = true; } else { - return false; + return ovmSafetyChecker.isBytecodeSafe(_code); } - } - /** A utility function used to check if bytecode has already been recorded as safe. + /** Used to check if bytecode has already been recorded as safe. * @param _codehash A bytes32 hash of the code */ function isRegisteredSafeBytecode( From 8f2c15e1dd39459fee72cd4e789df779cf22a27c Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 1 Mar 2021 15:13:04 -0500 Subject: [PATCH 08/39] Add gas test output for em.run() --- test/contracts/OVM/execution/run.gas-spec.ts | 148 +++++++++++++++++++ test/helpers/gas/gas.ts | 26 ++++ test/helpers/gas/index.ts | 1 + test/helpers/index.ts | 1 + test/helpers/utils/custom-deployer.ts | 18 +++ test/helpers/utils/index.ts | 1 + 6 files changed, 195 insertions(+) create mode 100644 test/contracts/OVM/execution/run.gas-spec.ts create mode 100644 test/helpers/gas/gas.ts create mode 100644 test/helpers/gas/index.ts create mode 100644 test/helpers/utils/custom-deployer.ts diff --git a/test/contracts/OVM/execution/run.gas-spec.ts b/test/contracts/OVM/execution/run.gas-spec.ts new file mode 100644 index 000000000..2cc5af34e --- /dev/null +++ b/test/contracts/OVM/execution/run.gas-spec.ts @@ -0,0 +1,148 @@ +import { expect } from '../../../setup' +import { deployContractCode } from '../../../helpers/utils' + +/* External Imports */ +import { ethers } from 'hardhat' +import { Contract, ContractFactory, Signer, BigNumber } from 'ethers' +import { smoddit, smockit, MockContract } from '@eth-optimism/smock' +import _ from 'lodash' + + + +/* Internal Imports */ +import { + makeAddressManager, + DUMMY_ACCOUNTS, + DUMMY_BYTES32, + ZERO_ADDRESS, + EMPTY_ACCOUNT_CODE_HASH, + NON_ZERO_ADDRESS, + NON_NULL_BYTES32, + STORAGE_XOR_VALUE, + setProxyTarget +} from '../../../helpers' +import { Address } from 'cluster' + +const DUMMY_ACCOUNT = DUMMY_ACCOUNTS[0] +const DUMMY_KEY = DUMMY_BYTES32[0] +const DUMMY_VALUE_1 = DUMMY_BYTES32[1] +const DUMMY_VALUE_2 = DUMMY_BYTES32[2] + +const DUMMY_GASMETERCONFIG = { + minTransactionGasLimit: 0, + maxTransactionGasLimit: NON_NULL_BYTES32, + maxGasPerQueuePerEpoch: NON_NULL_BYTES32, + secondsPerEpoch: NON_NULL_BYTES32, +} + +const DUMMY_GLOBALCONTEXT = { + ovmCHAINID: 420, +} + +const QUEUE_ORIGIN = { + SEQUENCER_QUEUE: 0, + L1TOL2_QUEUE: 1 +} + +let DUMMY_TRANSACTION = { + timestamp: 111111111111, + blockNumber: 20, + l1QueueOrigin: QUEUE_ORIGIN.SEQUENCER_QUEUE, + l1TxOrigin: NON_ZERO_ADDRESS, + entrypoint: NON_ZERO_ADDRESS, // update this below + gasLimit: 10_000_000, + data: 0 +} + +describe.only('OVM_ExecutionManager gas consumption', () => { + let wallet: Signer + before(async () => { + ;[wallet] = await ethers.getSigners() + }) + + let Factory__OVM_ExecutionManager: ContractFactory + let MOCK__STATE_MANAGER: MockContract + let Helper_GasMeasurer: Contract + let AddressManager: Contract + let targetContractAddress: string + before(async () => { + Factory__OVM_ExecutionManager = await ethers.getContractFactory( + 'OVM_ExecutionManager' + ) + + Helper_GasMeasurer = await ( + await (await ethers.getContractFactory('Helper_GasMeasurer')).deploy() + ).connect(wallet) + + // Deploy a simple contract that just returns successfully with no data + targetContractAddress = await deployContractCode('60206001f3', wallet, 10_000_000) + DUMMY_TRANSACTION.entrypoint = targetContractAddress + + AddressManager = await makeAddressManager() + + // deploy the state manager and mock it for the state transitioner + MOCK__STATE_MANAGER = await smockit( + await ( + await ethers.getContractFactory('OVM_StateManager') + ).deploy(NON_ZERO_ADDRESS) + ) + + MOCK__STATE_MANAGER.smocked.isAuthenticated.will.return.with(true) + MOCK__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with(targetContractAddress) + MOCK__STATE_MANAGER.smocked.hasAccount.will.return.with(true) + MOCK__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) + + await AddressManager.setAddress( + 'OVM_StateManagerFactory', + MOCK__STATE_MANAGER.address + ) + }) + + + let OVM_ExecutionManager: Contract + beforeEach(async () => { + OVM_ExecutionManager = ( + await Factory__OVM_ExecutionManager.deploy( + AddressManager.address, // safetychecker won't be called for very simple test cases + DUMMY_GASMETERCONFIG, + DUMMY_GLOBALCONTEXT + ) + ).connect(wallet) + }) + + const getSMGasCost = async ( + methodName: string, + methodArgs: Array = [] + ): Promise => { + const gasCost: number = await Helper_GasMeasurer.callStatic.measureCallGas( + OVM_ExecutionManager.address, + OVM_ExecutionManager.interface.encodeFunctionData(methodName, methodArgs) + ) + console.log(` calculated gas cost of ${gasCost}`) + + return gasCost + } + + const measure = async ( + methodName: string, + // methodArgs: Array, + getMethodArgs: () => Promise>, + doFirst: () => Promise = async () => { + return + } + ) => { + it('measured consumption!', async () => { + await doFirst() + await getSMGasCost(methodName, await getMethodArgs()) + // await getSMGasCost(methodName, methodArgs) + }) + } + + + describe('Measure cost of a very simple contract', async () => { + console.log('MOCK__STATE_MANAGER.address: ', MOCK__STATE_MANAGER) + measure('run', async () => { + return [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] + }) + }) +}) \ No newline at end of file diff --git a/test/helpers/gas/gas.ts b/test/helpers/gas/gas.ts new file mode 100644 index 000000000..d38406720 --- /dev/null +++ b/test/helpers/gas/gas.ts @@ -0,0 +1,26 @@ +export const a = null +// export const measure = ( +// methodName: string, +// methodArgs: Array = [], +// doFirst: () => Promise = async () => { +// return +// } +// ) => { +// it('measured consumption!', async () => { +// await doFirst() +// await getSMGasCost(methodName, methodArgs) +// }) +// } + +// export const getSMGasCost = async ( +// methodName: string, +// methodArgs: Array = [] +// ): Promise => { +// const gasCost: number = await Helper_GasMeasurer.callStatic.measureCallGas( +// OVM_ExecutionManager.address, +// OVM_ExecutionManager.interface.encodeFunctionData(methodName, methodArgs) +// ) +// console.log(` calculated gas cost of ${gasCost}`) + +// return gasCost +// } \ No newline at end of file diff --git a/test/helpers/gas/index.ts b/test/helpers/gas/index.ts new file mode 100644 index 000000000..45184d9da --- /dev/null +++ b/test/helpers/gas/index.ts @@ -0,0 +1 @@ +export * from './' \ No newline at end of file diff --git a/test/helpers/index.ts b/test/helpers/index.ts index 3aabffcca..a2ddca39b 100644 --- a/test/helpers/index.ts +++ b/test/helpers/index.ts @@ -6,3 +6,4 @@ export * from './utils' export * from './codec' export * from './test-runner' export * from './trie' +export * from './gas' diff --git a/test/helpers/utils/custom-deployer.ts b/test/helpers/utils/custom-deployer.ts new file mode 100644 index 000000000..1d2940fa1 --- /dev/null +++ b/test/helpers/utils/custom-deployer.ts @@ -0,0 +1,18 @@ +import { Signer } from 'ethers' +import { toHexString } from '../../../src/utils' + +export const deployContractCode = async (code: string, signer: Signer, gasLimit: number): Promise => { + // "Magic" prefix to be prepended to the contract code. Contains a series of opcodes that will + // copy the given code into memory and return it, thereby storing at the contract address. + const prefix = '0x600D380380600D6000396000f3' + const deployCode = prefix + toHexString(code).slice(2) + + const response = await signer.sendTransaction({ + to: null, + data: deployCode, + gasLimit, + }) + + const result = await response.wait() + return result.contractAddress +} \ No newline at end of file diff --git a/test/helpers/utils/index.ts b/test/helpers/utils/index.ts index 640444da3..cda5fd8ed 100644 --- a/test/helpers/utils/index.ts +++ b/test/helpers/utils/index.ts @@ -1,2 +1,3 @@ export * from '../../../src/utils' export * from './eth-time' +export * from './custom-deployer' From df0560dafe6520a7bf405fd044ae4d026f010ae1 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 1 Mar 2021 20:25:09 -0500 Subject: [PATCH 09/39] Move gas helper code to util' --- ...ec.ts => OVM_ExecutionManager.gas-spec.ts} | 53 +++++-------------- test/helpers/gas/gas.ts | 48 ++++++++--------- test/helpers/gas/index.ts | 2 +- 3 files changed, 39 insertions(+), 64 deletions(-) rename test/contracts/OVM/execution/{run.gas-spec.ts => OVM_ExecutionManager.gas-spec.ts} (71%) diff --git a/test/contracts/OVM/execution/run.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts similarity index 71% rename from test/contracts/OVM/execution/run.gas-spec.ts rename to test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 2cc5af34e..b823a869b 100644 --- a/test/contracts/OVM/execution/run.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -8,7 +8,6 @@ import { smoddit, smockit, MockContract } from '@eth-optimism/smock' import _ from 'lodash' - /* Internal Imports */ import { makeAddressManager, @@ -19,7 +18,8 @@ import { NON_ZERO_ADDRESS, NON_NULL_BYTES32, STORAGE_XOR_VALUE, - setProxyTarget + setProxyTarget, + GasMeasurement } from '../../../helpers' import { Address } from 'cluster' @@ -65,14 +65,11 @@ describe.only('OVM_ExecutionManager gas consumption', () => { let Helper_GasMeasurer: Contract let AddressManager: Contract let targetContractAddress: string + let gasMeasurement: GasMeasurement before(async () => { Factory__OVM_ExecutionManager = await ethers.getContractFactory( 'OVM_ExecutionManager' ) - - Helper_GasMeasurer = await ( - await (await ethers.getContractFactory('Helper_GasMeasurer')).deploy() - ).connect(wallet) // Deploy a simple contract that just returns successfully with no data targetContractAddress = await deployContractCode('60206001f3', wallet, 10_000_000) @@ -87,6 +84,7 @@ describe.only('OVM_ExecutionManager gas consumption', () => { ).deploy(NON_ZERO_ADDRESS) ) + // Setup the SM to satisfy all the checks executed during EM.run() MOCK__STATE_MANAGER.smocked.isAuthenticated.will.return.with(true) MOCK__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with(targetContractAddress) MOCK__STATE_MANAGER.smocked.hasAccount.will.return.with(true) @@ -96,6 +94,9 @@ describe.only('OVM_ExecutionManager gas consumption', () => { 'OVM_StateManagerFactory', MOCK__STATE_MANAGER.address ) + + gasMeasurement = new GasMeasurement() + await gasMeasurement.init(wallet) }) @@ -103,46 +104,20 @@ describe.only('OVM_ExecutionManager gas consumption', () => { beforeEach(async () => { OVM_ExecutionManager = ( await Factory__OVM_ExecutionManager.deploy( - AddressManager.address, // safetychecker won't be called for very simple test cases + AddressManager.address, DUMMY_GASMETERCONFIG, DUMMY_GLOBALCONTEXT ) ).connect(wallet) }) - const getSMGasCost = async ( - methodName: string, - methodArgs: Array = [] - ): Promise => { - const gasCost: number = await Helper_GasMeasurer.callStatic.measureCallGas( - OVM_ExecutionManager.address, - OVM_ExecutionManager.interface.encodeFunctionData(methodName, methodArgs) - ) - console.log(` calculated gas cost of ${gasCost}`) - - return gasCost - } - - const measure = async ( - methodName: string, - // methodArgs: Array, - getMethodArgs: () => Promise>, - doFirst: () => Promise = async () => { - return - } - ) => { - it('measured consumption!', async () => { - await doFirst() - await getSMGasCost(methodName, await getMethodArgs()) - // await getSMGasCost(methodName, methodArgs) - }) - } - - describe('Measure cost of a very simple contract', async () => { - console.log('MOCK__STATE_MANAGER.address: ', MOCK__STATE_MANAGER) - measure('run', async () => { - return [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] + it('Gas cost of run', async () => { + let gasCost = await gasMeasurement.getGasCost( + OVM_ExecutionManager, 'run', + [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] + ) + console.log(`calculated gas cost of ${gasCost}`) }) }) }) \ No newline at end of file diff --git a/test/helpers/gas/gas.ts b/test/helpers/gas/gas.ts index d38406720..15f2b0740 100644 --- a/test/helpers/gas/gas.ts +++ b/test/helpers/gas/gas.ts @@ -1,26 +1,26 @@ -export const a = null -// export const measure = ( -// methodName: string, -// methodArgs: Array = [], -// doFirst: () => Promise = async () => { -// return -// } -// ) => { -// it('measured consumption!', async () => { -// await doFirst() -// await getSMGasCost(methodName, methodArgs) -// }) -// } +import { ethers } from 'hardhat' +import { Contract, Signer } from 'ethers' -// export const getSMGasCost = async ( -// methodName: string, -// methodArgs: Array = [] -// ): Promise => { -// const gasCost: number = await Helper_GasMeasurer.callStatic.measureCallGas( -// OVM_ExecutionManager.address, -// OVM_ExecutionManager.interface.encodeFunctionData(methodName, methodArgs) -// ) -// console.log(` calculated gas cost of ${gasCost}`) +export class GasMeasurement { + GasMeasurementContract: Contract -// return gasCost -// } \ No newline at end of file + public async init(wallet: Signer){ + this.GasMeasurementContract = await ( + await (await ethers.getContractFactory('Helper_GasMeasurer')).deploy() + ).connect(wallet) + } + + public async getGasCost( + targetContract: Contract, + methodName: string, + methodArgs: Array = [] + ): Promise + { + const gasCost: number = await this.GasMeasurementContract.callStatic.measureCallGas( + targetContract.address, + targetContract.interface.encodeFunctionData(methodName, methodArgs) + ) + + return gasCost + } +} \ No newline at end of file diff --git a/test/helpers/gas/index.ts b/test/helpers/gas/index.ts index 45184d9da..b23eada0c 100644 --- a/test/helpers/gas/index.ts +++ b/test/helpers/gas/index.ts @@ -1 +1 @@ -export * from './' \ No newline at end of file +export * from './gas' \ No newline at end of file From 0abc190d145446cb0fa64bb886bcb656953154d5 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 1 Mar 2021 20:47:39 -0500 Subject: [PATCH 10/39] Use GasMeasurement class in SM gas spec --- .../execution/OVM_StateManager.gas-spec.ts | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/test/contracts/OVM/execution/OVM_StateManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_StateManager.gas-spec.ts index e0e449d13..029909d4d 100644 --- a/test/contracts/OVM/execution/OVM_StateManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_StateManager.gas-spec.ts @@ -14,6 +14,7 @@ import { NON_ZERO_ADDRESS, NON_NULL_BYTES32, STORAGE_XOR_VALUE, + GasMeasurement, } from '../../../helpers' const DUMMY_ACCOUNT = DUMMY_ACCOUNTS[0] @@ -29,23 +30,23 @@ describe('OVM_StateManager gas consumption', () => { let Factory__OVM_StateManager: ContractFactory let Helper_GasMeasurer: Contract + let gasMeasurement: GasMeasurement before(async () => { Factory__OVM_StateManager = await ethers.getContractFactory( 'OVM_StateManager' ) - - Helper_GasMeasurer = await ( - await (await ethers.getContractFactory('Helper_GasMeasurer')).deploy() - ).connect(owner) + gasMeasurement = new GasMeasurement() + await gasMeasurement.init(owner) }) + let OVM_StateManager: Contract beforeEach(async () => { OVM_StateManager = ( await Factory__OVM_StateManager.deploy(await owner.getAddress()) ).connect(owner) - await OVM_StateManager.setExecutionManager(Helper_GasMeasurer.address) + await OVM_StateManager.setExecutionManager(gasMeasurement.GasMeasurementContract.address) }) const measure = ( @@ -57,23 +58,11 @@ describe('OVM_StateManager gas consumption', () => { ) => { it('measured consumption!', async () => { await doFirst() - await getSMGasCost(methodName, methodArgs) + let gasCost = await gasMeasurement.getGasCost(OVM_StateManager, methodName, methodArgs) + console.log(` calculated gas cost of ${gasCost}`) }) } - const getSMGasCost = async ( - methodName: string, - methodArgs: Array = [] - ): Promise => { - const gasCost: number = await Helper_GasMeasurer.callStatic.measureCallGas( - OVM_StateManager.address, - OVM_StateManager.interface.encodeFunctionData(methodName, methodArgs) - ) - console.log(` calculated gas cost of ${gasCost}`) - - return gasCost - } - const setupFreshAccount = async () => { await OVM_StateManager.putAccount(DUMMY_ACCOUNT.address, { ...DUMMY_ACCOUNT.data, From 99c6d7b2571ee355b0c1d8617117623bb93837ca Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 1 Mar 2021 21:03:00 -0500 Subject: [PATCH 11/39] Add expect statements --- .../OVM/execution/OVM_ExecutionManager.gas-spec.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index b823a869b..8a00dddc6 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -3,7 +3,7 @@ import { deployContractCode } from '../../../helpers/utils' /* External Imports */ import { ethers } from 'hardhat' -import { Contract, ContractFactory, Signer, BigNumber } from 'ethers' +import { Contract, ContractFactory, Signer } from 'ethers' import { smoddit, smockit, MockContract } from '@eth-optimism/smock' import _ from 'lodash' @@ -19,7 +19,7 @@ import { NON_NULL_BYTES32, STORAGE_XOR_VALUE, setProxyTarget, - GasMeasurement + GasMeasurement, } from '../../../helpers' import { Address } from 'cluster' @@ -118,6 +118,13 @@ describe.only('OVM_ExecutionManager gas consumption', () => { [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] ) console.log(`calculated gas cost of ${gasCost}`) + + let benchmark:number = 226_516 + expect(gasCost).to.be.lte(benchmark) + expect(gasCost).to.be.gte( + benchmark - 1_000, + "Gas cost has significantly decreased, consider updating the benchmark to reflect the change" + ) }) }) }) \ No newline at end of file From c5250a9accc2c7d8f1038acfd34002a865b10f57 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 1 Mar 2021 21:04:22 -0500 Subject: [PATCH 12/39] remove only() --- test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 8a00dddc6..5adc8d356 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -54,7 +54,7 @@ let DUMMY_TRANSACTION = { data: 0 } -describe.only('OVM_ExecutionManager gas consumption', () => { +describe('OVM_ExecutionManager gas consumption', () => { let wallet: Signer before(async () => { ;[wallet] = await ethers.getSigners() From c094e1f8f2ad498fedbfe7cf383572389aefac79 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 2 Mar 2021 22:49:54 -0500 Subject: [PATCH 13/39] save wip --- .../OVM/execution/OVM_ExecutionManager.sol | 11 ++++++++ .../OVM/execution/OVM_SafetyCache.sol | 2 ++ .../iOVM/execution/iOVM_SafetyCache.sol | 10 ++++---- .../OVM_ExecutionManager/ovmCREATE.spec.ts | 1 + .../OVM_ExecutionManager/ovmSLOAD.spec.ts | 1 + test/helpers/test-runner/test-runner.ts | 25 ++++++++++++++++++- 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index f3d4c8782..f6d27ba28 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -3,6 +3,9 @@ pragma solidity >0.5.0 <0.8.0; pragma experimental ABIEncoderV2; +import "hardhat/console.sol"; + + /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; @@ -14,6 +17,7 @@ import { iOVM_ExecutionManager } from "../../iOVM/execution/iOVM_ExecutionManage /* External Interface Imports */ import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol"; import { iOVM_SafetyCache } from "../../iOVM/execution/iOVM_SafetyCache.sol"; +import { iOVM_SafetyChecker } from "../../iOVM/execution/iOVM_SafetyChecker.sol"; /* Contract Imports */ import { OVM_ECDSAContractAccount } from "../accounts/OVM_ECDSAContractAccount.sol"; @@ -42,6 +46,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ********************************/ iOVM_SafetyCache internal ovmSafetyCache; + iOVM_SafetyChecker internal ovmSafetyChecker; iOVM_StateManager internal ovmStateManager; @@ -802,6 +807,8 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { return; } + console.log(1); + // We need to be sure that the user isn't trying to use a contract creation to overwrite // some existing contract. On L1, users will prove that no contract exists at the address // and the OVM_FraudVerifier will populate the code hash of this address with a special @@ -810,10 +817,13 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _revertWithFlag(RevertFlag.CREATE_COLLISION); } + console.log(2); + // Check the creation bytecode against the Safety Cache and Safety Checker. if (ovmSafetyCache.checkAndRegisterSafeBytecode(_bytecode) == false) { _revertWithFlag(RevertFlag.UNSAFE_BYTECODE); } + console.log(3); // We always need to initialize the contract with the default account values. _initPendingAccount(_address); @@ -831,6 +841,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { if (ethAddress == address(0)) { _revertWithFlag(RevertFlag.CREATE_EXCEPTION); } + console.log(4); // Here we pull out the revert flag that would've been set during creation code. Now that // we're out of creation code again, we can just revert normally while passing the flag diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol index 49399a2ea..bbd0b2f9e 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol @@ -64,6 +64,7 @@ contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { function checkAndRegisterSafeBytecode( bytes memory _code ) + override external returns ( bool @@ -83,6 +84,7 @@ contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { function isRegisteredSafeBytecode( bytes32 _codehash ) + override external view returns ( diff --git a/contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyCache.sol b/contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyCache.sol index 1ef311ef0..13dfa20c7 100644 --- a/contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyCache.sol +++ b/contracts/optimistic-ethereum/iOVM/execution/iOVM_SafetyCache.sol @@ -6,11 +6,11 @@ pragma solidity >0.5.0 <0.8.0; */ interface iOVM_SafetyCache { - /******************** - * External Functions * - ********************/ - function checkAndRegisterSafeBytecode(bytes memory _code) external returns (bool) + /********************* + * External Functions * + **********************/ + function checkAndRegisterSafeBytecode(bytes memory _code) external returns (bool); - function isRegisteredSafeBytecode(bytes32 _codehash) external view returns (bool) + function isRegisteredSafeBytecode(bytes32 _codehash) external view returns (bool); } diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATE.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATE.spec.ts index 849abb166..e2bc2c3d1 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATE.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATE.spec.ts @@ -40,6 +40,7 @@ const test_ovmCREATE: TestDefinition = { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', ovmSafetyChecker: '$OVM_SAFETY_CHECKER', + ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, }, diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSLOAD.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSLOAD.spec.ts index eb401998a..bc0628635 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSLOAD.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSLOAD.spec.ts @@ -14,6 +14,7 @@ const test_ovmSLOAD: TestDefinition = { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', ovmSafetyChecker: '$OVM_SAFETY_CHECKER', + ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, }, diff --git a/test/helpers/test-runner/test-runner.ts b/test/helpers/test-runner/test-runner.ts index 5232d6633..ce1aa6c58 100644 --- a/test/helpers/test-runner/test-runner.ts +++ b/test/helpers/test-runner/test-runner.ts @@ -43,6 +43,7 @@ export class ExecutionManagerTestRunner { private snapshot: string private contracts: { OVM_SafetyChecker: Contract + OVM_SafetyCache: Contract OVM_StateManager: ModifiableContract OVM_ExecutionManager: ModifiableContract Helper_TestRunner: Contract @@ -50,6 +51,7 @@ export class ExecutionManagerTestRunner { OVM_DeployerWhitelist: Contract } = { OVM_SafetyChecker: undefined, + OVM_SafetyCache: undefined, OVM_StateManager: undefined, OVM_ExecutionManager: undefined, Helper_TestRunner: undefined, @@ -89,7 +91,7 @@ export class ExecutionManagerTestRunner { )), (test.postState = test.postState || {}) - describe(`OVM_ExecutionManager Test: ${test.name}`, () => { + describe.only(`OVM_ExecutionManager Test: ${test.name}`, () => { test.subTests?.map((subTest) => { this.run({ ...subTest, @@ -188,6 +190,7 @@ export class ExecutionManagerTestRunner { await ethers.getContractFactory('Lib_AddressManager') ).deploy() + // Setup SafetyChecker const SafetyChecker = await ( await ethers.getContractFactory('OVM_SafetyChecker') ).deploy() @@ -202,12 +205,29 @@ export class ExecutionManagerTestRunner { this.contracts.OVM_SafetyChecker.address ) + // Setup SafetyCache + const SafetyCache = await ( + await ethers.getContractFactory('OVM_SafetyCache') + ).deploy(AddressManager.address) + + const MockSafetyCache = await smockit(SafetyCache) + MockSafetyCache.smocked.isRegisteredSafeBytecode.will.return.with(true) + + this.contracts.OVM_SafetyCache = MockSafetyCache + + await AddressManager.setAddress( + 'OVM_SafetyCache', + this.contracts.OVM_SafetyCache.address + ) + + // Setup DeployerWhitelist const DeployerWhitelist = await ( await ethers.getContractFactory('OVM_DeployerWhitelist') ).deploy() this.contracts.OVM_DeployerWhitelist = DeployerWhitelist + // Setup EM this.contracts.OVM_ExecutionManager = await ( await smoddit('OVM_ExecutionManager') ).deploy( @@ -223,6 +243,7 @@ export class ExecutionManagerTestRunner { } ) + // Setup SM this.contracts.OVM_StateManager = await ( await smoddit('OVM_StateManager') ).deploy(await this.contracts.OVM_ExecutionManager.signer.getAddress()) @@ -251,6 +272,8 @@ export class ExecutionManagerTestRunner { return this.contracts.OVM_ExecutionManager.address } else if (kv === '$OVM_STATE_MANAGER') { return this.contracts.OVM_StateManager.address + } else if (kv === '$OVM_SAFETY_CACHE') { + return this.contracts.OVM_SafetyCache.address } else if (kv === '$OVM_SAFETY_CHECKER') { return this.contracts.OVM_SafetyChecker.address } else if (kv === '$OVM_CALL_HELPER') { From 16d80693fddef2fef11cba9198874295ac8a4e81 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 2 Mar 2021 23:27:11 -0500 Subject: [PATCH 14/39] remove console.log from solidity --- .../OVM/execution/OVM_ExecutionManager.sol | 9 --------- test/helpers/test-runner/test-runner.ts | 1 + 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index f6d27ba28..ff94c621d 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -3,9 +3,6 @@ pragma solidity >0.5.0 <0.8.0; pragma experimental ABIEncoderV2; -import "hardhat/console.sol"; - - /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; @@ -807,8 +804,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { return; } - console.log(1); - // We need to be sure that the user isn't trying to use a contract creation to overwrite // some existing contract. On L1, users will prove that no contract exists at the address // and the OVM_FraudVerifier will populate the code hash of this address with a special @@ -817,13 +812,10 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _revertWithFlag(RevertFlag.CREATE_COLLISION); } - console.log(2); - // Check the creation bytecode against the Safety Cache and Safety Checker. if (ovmSafetyCache.checkAndRegisterSafeBytecode(_bytecode) == false) { _revertWithFlag(RevertFlag.UNSAFE_BYTECODE); } - console.log(3); // We always need to initialize the contract with the default account values. _initPendingAccount(_address); @@ -841,7 +833,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { if (ethAddress == address(0)) { _revertWithFlag(RevertFlag.CREATE_EXCEPTION); } - console.log(4); // Here we pull out the revert flag that would've been set during creation code. Now that // we're out of creation code again, we can just revert normally while passing the flag diff --git a/test/helpers/test-runner/test-runner.ts b/test/helpers/test-runner/test-runner.ts index ce1aa6c58..1959a83e9 100644 --- a/test/helpers/test-runner/test-runner.ts +++ b/test/helpers/test-runner/test-runner.ts @@ -212,6 +212,7 @@ export class ExecutionManagerTestRunner { const MockSafetyCache = await smockit(SafetyCache) MockSafetyCache.smocked.isRegisteredSafeBytecode.will.return.with(true) + MockSafetyCache.smocked.checkAndRegisterSafeBytecode.will.return.with(true) this.contracts.OVM_SafetyCache = MockSafetyCache From a5bc99acc2299925f9e446922c2355035483ffbb Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 3 Mar 2021 14:40:43 -0500 Subject: [PATCH 15/39] Add cache to test-runner --- test/helpers/test-runner/test-runner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/helpers/test-runner/test-runner.ts b/test/helpers/test-runner/test-runner.ts index d7db09d04..45beb1fa4 100644 --- a/test/helpers/test-runner/test-runner.ts +++ b/test/helpers/test-runner/test-runner.ts @@ -92,7 +92,7 @@ export class ExecutionManagerTestRunner { )), (test.postState = test.postState || {}) - describe.only(`OVM_ExecutionManager Test: ${test.name}`, () => { + describe(`OVM_ExecutionManager Test: ${test.name}`, () => { test.subTests?.map((subTest) => { this.run({ ...subTest, From 3ef93a892be8464da0df20e06e7c7f353652fe3b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 3 Mar 2021 14:47:43 -0500 Subject: [PATCH 16/39] Add WIP test case. --- .../OVM_ExecutionManager.gas-spec.ts | 71 ++++++++++++++----- 1 file changed, 52 insertions(+), 19 deletions(-) diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index f3ed69447..ed07027bf 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -40,30 +40,18 @@ const DUMMY_TRANSACTION = { data: 0, } -describe('OVM_ExecutionManager gas consumption', () => { +describe.only('OVM_ExecutionManager gas consumption', () => { let wallet: Signer - before(async () => { - ;[wallet] = await ethers.getSigners() - }) - let Factory__OVM_ExecutionManager: ContractFactory let MOCK__STATE_MANAGER: MockContract let AddressManager: Contract - let targetContractAddress: string let gasMeasurement: GasMeasurement before(async () => { + ;[wallet] = await ethers.getSigners() Factory__OVM_ExecutionManager = await ethers.getContractFactory( 'OVM_ExecutionManager' ) - // Deploy a simple contract that just returns successfully with no data - targetContractAddress = await deployContractCode( - '60206001f3', - wallet, - 10_000_000 - ) - DUMMY_TRANSACTION.entrypoint = targetContractAddress - AddressManager = await makeAddressManager() // deploy the state manager and mock it for the state transitioner @@ -75,9 +63,6 @@ describe('OVM_ExecutionManager gas consumption', () => { // Setup the SM to satisfy all the checks executed during EM.run() MOCK__STATE_MANAGER.smocked.isAuthenticated.will.return.with(true) - MOCK__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( - targetContractAddress - ) MOCK__STATE_MANAGER.smocked.hasAccount.will.return.with(true) MOCK__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) @@ -102,15 +87,63 @@ describe('OVM_ExecutionManager gas consumption', () => { }) describe('Measure cost of a very simple contract', async () => { + + let targetContractAddress: string + before(async () => { + // Deploy a simple OVM-safe contract that just deploys a another contract + targetContractAddress = await deployContractCode( + '60206001f3', + wallet, + 10_000_000 + ) + DUMMY_TRANSACTION.entrypoint = targetContractAddress + MOCK__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( + targetContractAddress + ) + }) + + it('Gas cost of run', async () => { + const gasCost = await gasMeasurement.getGasCost( + OVM_ExecutionManager, + 'run', + [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] + ) + console.log(` calculated gas cost of ${gasCost}`) + + const benchmark: number = 229_371 + expect(gasCost).to.be.lte(benchmark) + expect(gasCost).to.be.gte( + benchmark - 1_000, + 'Gas cost has significantly decreased, consider updating the benchmark to reflect the change' + ) + }) + }) + + describe('Measure cost of deploying a very simple contract', async () => { + + let targetContractAddress: string + before(async () => { + // Deploy a simple OVM-safe contract that just deploys another contract + targetContractAddress = await deployContractCode( + '60206001f3', + wallet, + 10_000_000 + ) + DUMMY_TRANSACTION.entrypoint = targetContractAddress + MOCK__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( + targetContractAddress + ) + }) + it('Gas cost of run', async () => { const gasCost = await gasMeasurement.getGasCost( OVM_ExecutionManager, 'run', [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] ) - console.log(`calculated gas cost of ${gasCost}`) + console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 226_516 + const benchmark: number = 229_371 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, From d74656107843b0dd1d412adfd6695d731ce34e54 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 3 Mar 2021 15:31:48 -0500 Subject: [PATCH 17/39] Add question comments --- .../OVM_ExecutionManager.gas-spec.ts | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index ed07027bf..47aebc63b 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -102,7 +102,7 @@ describe.only('OVM_ExecutionManager gas consumption', () => { ) }) - it('Gas cost of run', async () => { + it('Gas cost of run()', async () => { const gasCost = await gasMeasurement.getGasCost( OVM_ExecutionManager, 'run', @@ -110,7 +110,7 @@ describe.only('OVM_ExecutionManager gas consumption', () => { ) console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 229_371 + const benchmark: number = 226_516 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, @@ -121,21 +121,11 @@ describe.only('OVM_ExecutionManager gas consumption', () => { describe('Measure cost of deploying a very simple contract', async () => { - let targetContractAddress: string - before(async () => { - // Deploy a simple OVM-safe contract that just deploys another contract - targetContractAddress = await deployContractCode( - '60206001f3', - wallet, - 10_000_000 - ) - DUMMY_TRANSACTION.entrypoint = targetContractAddress - MOCK__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( - targetContractAddress - ) - }) + - it('Gas cost of run', async () => { + it('Gas cost of basic contract deployment', async () => { + // what does the DUMMY_TRANSACTION need to be to deploy a simple transaction? + // Do I need to go through a proxy EOA? const gasCost = await gasMeasurement.getGasCost( OVM_ExecutionManager, 'run', @@ -143,7 +133,7 @@ describe.only('OVM_ExecutionManager gas consumption', () => { ) console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 229_371 + const benchmark: number = 226_516 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, From 61fe4adea7726c2c1bc69c25eaa7536c4d1ab510 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Thu, 4 Mar 2021 10:10:40 -0500 Subject: [PATCH 18/39] Save WIP --- .../OVM/execution/OVM_SafetyCache.sol | 11 +-- .../test-helpers/Helper_SimpleOvmDeployer.sol | 15 ++++ .../OVM_ExecutionManager.gas-spec.ts | 72 +++++++++++++------ 3 files changed, 74 insertions(+), 24 deletions(-) create mode 100644 contracts/test-helpers/Helper_SimpleOvmDeployer.sol diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol index bbd0b2f9e..099434ed5 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol @@ -70,12 +70,15 @@ contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { bool ) { bytes32 codehash = keccak256(abi.encode(_code)); - if(isSafeCodehash[codehash] == true) { return true; - } else { - return ovmSafetyChecker.isBytecodeSafe(_code); } + + bool safe = ovmSafetyChecker.isBytecodeSafe(_code); + if(safe) { + isSafeCodehash[codehash] = true; + } + return safe; } /** Used to check if bytecode has already been recorded as safe. @@ -91,6 +94,6 @@ contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { bool ) { - return (isSafeCodehash[_codehash] == true); + return isSafeCodehash[_codehash] == true; } } diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol new file mode 100644 index 000000000..bbb957af3 --- /dev/null +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT +import { Lib_SafeExecutionManagerWrapper } from "../optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol"; + + +pragma solidity >0.5.0 <0.8.0; + +contract Helper_SimpleOvmDeployer { + + fallback() + external + { + Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), "00"); + } +} diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 47aebc63b..5a435260f 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -42,15 +42,13 @@ const DUMMY_TRANSACTION = { describe.only('OVM_ExecutionManager gas consumption', () => { let wallet: Signer - let Factory__OVM_ExecutionManager: ContractFactory let MOCK__STATE_MANAGER: MockContract let AddressManager: Contract let gasMeasurement: GasMeasurement + let Factory__OVM_ExecutionManager: ContractFactory + let OVM_ExecutionManager: Contract before(async () => { ;[wallet] = await ethers.getSigners() - Factory__OVM_ExecutionManager = await ethers.getContractFactory( - 'OVM_ExecutionManager' - ) AddressManager = await makeAddressManager() @@ -71,12 +69,10 @@ describe.only('OVM_ExecutionManager gas consumption', () => { MOCK__STATE_MANAGER.address ) - gasMeasurement = new GasMeasurement() - await gasMeasurement.init(wallet) - }) - - let OVM_ExecutionManager: Contract - beforeEach(async () => { + // Setup the EM + Factory__OVM_ExecutionManager = await ethers.getContractFactory( + 'OVM_ExecutionManager' + ) OVM_ExecutionManager = ( await Factory__OVM_ExecutionManager.deploy( AddressManager.address, @@ -84,15 +80,19 @@ describe.only('OVM_ExecutionManager gas consumption', () => { DUMMY_GLOBALCONTEXT ) ).connect(wallet) + + // Deploy GasMeasurement utility + gasMeasurement = new GasMeasurement() + await gasMeasurement.init(wallet) }) - describe('Measure cost of a very simple contract', async () => { + describe('Measure cost of executing a very simple contract', async () => { let targetContractAddress: string before(async () => { - // Deploy a simple OVM-safe contract that just deploys a another contract + // Deploy a simple OVM-safe contract which is just `STOP` targetContractAddress = await deployContractCode( - '60206001f3', + '00', wallet, 10_000_000 ) @@ -102,7 +102,9 @@ describe.only('OVM_ExecutionManager gas consumption', () => { ) }) - it('Gas cost of run()', async () => { + it('Gas benchmark: cost of run()', async () => { + // by setting the entrypoint to our minimal contract, and smocking the SM + // we measure mostly the overhead of EM.run() const gasCost = await gasMeasurement.getGasCost( OVM_ExecutionManager, 'run', @@ -119,13 +121,37 @@ describe.only('OVM_ExecutionManager gas consumption', () => { }) }) - describe('Measure cost of deploying a very simple contract', async () => { - - + describe('Measure cost of deploying a simple contract', async () => { + let simpleDeployer: Contract + before(async () => { + // Deploy a simple OVM-safe contract that just deploys a another contract + simpleDeployer = await ( + await ethers.getContractFactory('Helper_SimpleOvmDeployer') + ).deploy() + DUMMY_TRANSACTION.entrypoint = simpleDeployer.address - it('Gas cost of basic contract deployment', async () => { - // what does the DUMMY_TRANSACTION need to be to deploy a simple transaction? - // Do I need to go through a proxy EOA? + MOCK__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( + simpleDeployer.address + ) + }) + + it('Benchmark un-chached contract deployment', async () => { + const gasCost = await gasMeasurement.getGasCost( + OVM_ExecutionManager, + 'run', + [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] + ) + console.log(` calculated gas cost of ${gasCost}`) + + const benchmark: number = 3_488_629 + expect(gasCost).to.be.lte(benchmark) + expect(gasCost).to.be.gte( + benchmark - 1_000, + 'Gas cost has significantly decreased, consider updating the benchmark to reflect the change' + ) + }) + + it('Gas benchmark: deploying a cached contract', async () => { const gasCost = await gasMeasurement.getGasCost( OVM_ExecutionManager, 'run', @@ -141,4 +167,10 @@ describe.only('OVM_ExecutionManager gas consumption', () => { ) }) }) + describe.skip('Measure cost of deploying a larger contract', async () => { + it('Benchmark un-chached contract deployment', async () => { + }) + it('Gas benchmark: deploying a cached contract', async () => { + }) + }) }) From 22178058d6e86322fd7174bf394c46c1c6adceed Mon Sep 17 00:00:00 2001 From: Maurelian Date: Fri, 5 Mar 2021 14:48:29 -0500 Subject: [PATCH 19/39] Save WIP status: debugging SM auth --- .../OVM/execution/OVM_ExecutionManager.sol | 9 +- .../OVM/execution/OVM_SafetyCache.sol | 7 ++ .../OVM/execution/OVM_StateManager.sol | 3 + .../test-helpers/Helper_SimpleOvmDeployer.sol | 6 + .../OVM_ExecutionManager.gas-spec.ts | 105 ++++++++++++++---- 5 files changed, 108 insertions(+), 22 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index ff94c621d..6b9d9bc3a 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -3,6 +3,9 @@ pragma solidity >0.5.0 <0.8.0; pragma experimental ABIEncoderV2; +import "hardhat/console.sol"; + + /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; @@ -86,6 +89,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { public Lib_AddressResolver(_libAddressManager) { + console.log('constructor'); ovmSafetyCache = iOVM_SafetyCache(resolve("OVM_SafetyCache")); gasMeterConfig = _gasMeterConfig; globalContext = _globalContext; @@ -812,6 +816,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _revertWithFlag(RevertFlag.CREATE_COLLISION); } + console.log('pre-check'); // Check the creation bytecode against the Safety Cache and Safety Checker. if (ovmSafetyCache.checkAndRegisterSafeBytecode(_bytecode) == false) { _revertWithFlag(RevertFlag.UNSAFE_BYTECODE); @@ -1179,7 +1184,9 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ) { _checkAccountLoad(_address); - return ovmStateManager.getAccountEthAddress(_address); + address gotten = ovmStateManager.getAccountEthAddress(_address); + // console.log('_getAccountEthAddress', _address, gotten); + return gotten; } /** diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol index 099434ed5..674796c2c 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol @@ -10,6 +10,9 @@ import { iOVM_SafetyCache } from "../../iOVM/execution/iOVM_SafetyCache.sol"; /* Inherited Interface Imports */ import { iOVM_SafetyChecker } from "../../iOVM/execution/iOVM_SafetyChecker.sol"; +import "hardhat/console.sol"; + + /** * @title OVM_SafetyCache * @dev This contract implements a simple registry for caching the hash of any bytecode strings which have @@ -70,11 +73,15 @@ contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { bool ) { bytes32 codehash = keccak256(abi.encode(_code)); + console.log("codehash: "); + console.logBytes32(codehash); + console.log(uint(codehash)); if(isSafeCodehash[codehash] == true) { return true; } bool safe = ovmSafetyChecker.isBytecodeSafe(_code); + console.log("safe: ", safe); if(safe) { isSafeCodehash[codehash] = true; } diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol index 25f056690..98327b1ce 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol @@ -2,6 +2,8 @@ pragma solidity >0.5.0 <0.8.0; pragma experimental ABIEncoderV2; +import "hardhat/console.sol"; + /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; @@ -69,6 +71,7 @@ contract OVM_StateManager is iOVM_StateManager { */ modifier authenticated() { // owner is the State Transitioner + console.log('caller: ', msg.sender); require( msg.sender == owner || msg.sender == ovmExecutionManager, "Function can only be called by authenticated addresses" diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol index bbb957af3..6b991fd07 100644 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -1,15 +1,21 @@ // SPDX-License-Identifier: UNLICENSED // SPDX-License-Identifier: MIT import { Lib_SafeExecutionManagerWrapper } from "../optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol"; +import "hardhat/console.sol"; pragma solidity >0.5.0 <0.8.0; contract Helper_SimpleOvmDeployer { + constructor(){ + console.log('Helper_SimpleOvmDeployer'); + } + fallback() external { Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), "00"); + console.log('deployed with bytecode: 0x00'); } } diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 5a435260f..b07fc08b0 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -4,7 +4,12 @@ import { deployContractCode } from '../../../helpers/utils' /* External Imports */ import { ethers } from 'hardhat' import { Contract, ContractFactory, Signer } from 'ethers' -import { smockit, MockContract } from '@eth-optimism/smock' +import { + smockit, + MockContract, + ModifiableContract, + smoddit +} from '@eth-optimism/smock' /* Internal Imports */ import { @@ -42,7 +47,12 @@ const DUMMY_TRANSACTION = { describe.only('OVM_ExecutionManager gas consumption', () => { let wallet: Signer - let MOCK__STATE_MANAGER: MockContract + let OVM_SafetyChecker: Contract + let OVM_SafetyCache: Contract + let MOCK__OVM_DeployerWhitelist: MockContract + + let MODDABLE__STATE_MANAGER: ModifiableContract + // let MOCK__STATE_MANAGER: MockContract let AddressManager: Contract let gasMeasurement: GasMeasurement let Factory__OVM_ExecutionManager: ContractFactory @@ -52,21 +62,32 @@ describe.only('OVM_ExecutionManager gas consumption', () => { AddressManager = await makeAddressManager() - // deploy the state manager and mock it for the state transitioner - MOCK__STATE_MANAGER = await smockit( - await (await ethers.getContractFactory('OVM_StateManager')).deploy( - NON_ZERO_ADDRESS - ) + // Deploy Safety Checker and register it with the Address Manager + OVM_SafetyChecker = await ( + await ethers.getContractFactory('OVM_SafetyChecker') + ).deploy() + await AddressManager.setAddress( + 'OVM_SafetyChecker', + OVM_SafetyChecker.address + ) + + // Deploy Safety Checker and register it with the Address Manager + OVM_SafetyCache = await ( + await ethers.getContractFactory('OVM_SafetyCache') + ).deploy(AddressManager.address) + await AddressManager.setAddress( + 'OVM_SafetyCache', + OVM_SafetyCache.address ) - // Setup the SM to satisfy all the checks executed during EM.run() - MOCK__STATE_MANAGER.smocked.isAuthenticated.will.return.with(true) - MOCK__STATE_MANAGER.smocked.hasAccount.will.return.with(true) - MOCK__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) - + // Setup Mock Deployer Whitelist and register it with the Address Manager + MOCK__OVM_DeployerWhitelist = await smockit( + await ethers.getContractFactory('OVM_DeployerWhitelist') + ) + MOCK__OVM_DeployerWhitelist.smocked.isDeployerAllowed.will.return.with(true) await AddressManager.setAddress( - 'OVM_StateManagerFactory', - MOCK__STATE_MANAGER.address + 'OVM_DeployerWhitelist', + MOCK__OVM_DeployerWhitelist.address ) // Setup the EM @@ -80,6 +101,47 @@ describe.only('OVM_ExecutionManager gas consumption', () => { DUMMY_GLOBALCONTEXT ) ).connect(wallet) + + // Setup the State Manger and modify it to allow execution to proceed + MODDABLE__STATE_MANAGER = await ( + await smoddit('OVM_StateManager') + ).deploy( + NON_ZERO_ADDRESS + ) + + // Setup the SM to satisfy all the checks executed during EM.run() + MODDABLE__STATE_MANAGER.smodify.set({ + ovmExecutionManager: OVM_ExecutionManager.address + }) + console.log('ovmem', await MODDABLE__STATE_MANAGER.ovmExecutionManager()) + console.log('owner', await MODDABLE__STATE_MANAGER.owner()) + // MODDABLE__STATE_MANAGER.smocked.hasAccount.will.return.with(true) + MODDABLE__STATE_MANAGER.smodify.set({ + accounts: { + [OVM_SafetyCache.address]: { + nonce: 0, + codeHash: NON_NULL_BYTES32, + ethAddress: OVM_SafetyCache.address, + }, + // todo remove if unneeded + // [OVM_SafetyChecker.address]: { + // nonce: 0, + // codeHash: NON_NULL_BYTES32, + // ethAddress: OVM_SafetyChecker.address, + // }, + [MOCK__OVM_DeployerWhitelist.address]: { + nonce: 0, + codeHash: NON_NULL_BYTES32, + ethAddress: MOCK__OVM_DeployerWhitelist.address, + }, + + }, + }) + // MODDABLE__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) + await MODDABLE__STATE_MANAGER.smodify.puttestAndSetAccountLoaded(OVM_SafetyCache.address); + await MODDABLE__STATE_MANAGER.smodify.puttestAndSetAccountLoaded(MOCK__OVM_DeployerWhitelist.address); + // MODDABLE__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) + // MODDABLE__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) // Deploy GasMeasurement utility gasMeasurement = new GasMeasurement() @@ -90,6 +152,7 @@ describe.only('OVM_ExecutionManager gas consumption', () => { let targetContractAddress: string before(async () => { + console.log('we here'); // Deploy a simple OVM-safe contract which is just `STOP` targetContractAddress = await deployContractCode( '00', @@ -97,7 +160,7 @@ describe.only('OVM_ExecutionManager gas consumption', () => { 10_000_000 ) DUMMY_TRANSACTION.entrypoint = targetContractAddress - MOCK__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( + MODDABLE__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( targetContractAddress ) }) @@ -108,7 +171,7 @@ describe.only('OVM_ExecutionManager gas consumption', () => { const gasCost = await gasMeasurement.getGasCost( OVM_ExecutionManager, 'run', - [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] + [DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address] ) console.log(` calculated gas cost of ${gasCost}`) @@ -130,16 +193,16 @@ describe.only('OVM_ExecutionManager gas consumption', () => { ).deploy() DUMMY_TRANSACTION.entrypoint = simpleDeployer.address - MOCK__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( + MODDABLE__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( simpleDeployer.address ) }) - it('Benchmark un-chached contract deployment', async () => { + it('Gas Benchmark: un-chached contract deployment', async () => { const gasCost = await gasMeasurement.getGasCost( OVM_ExecutionManager, 'run', - [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] + [DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address] ) console.log(` calculated gas cost of ${gasCost}`) @@ -151,11 +214,11 @@ describe.only('OVM_ExecutionManager gas consumption', () => { ) }) - it('Gas benchmark: deploying a cached contract', async () => { + it('Gas Benchmark: deploying a cached contract', async () => { const gasCost = await gasMeasurement.getGasCost( OVM_ExecutionManager, 'run', - [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] + [DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address] ) console.log(` calculated gas cost of ${gasCost}`) From 0f6c144a3f21a9d48440a8c347c6c1b2df5a2dc4 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Sun, 7 Mar 2021 10:49:47 -0500 Subject: [PATCH 20/39] ongoing debugging - pre-reset --- .../OVM/execution/OVM_ExecutionManager.sol | 6 +- .../OVM/execution/OVM_StateManager.sol | 3 + .../test-helpers/Helper_SimpleOvmDeployer.sol | 2 +- .../OVM_ExecutionManager.gas-spec.ts | 88 +++++++++++++------ 4 files changed, 67 insertions(+), 32 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index 6b9d9bc3a..aa337a783 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -175,6 +175,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // Make sure this function can't be called by anyone except the owner of the // OVM_StateManager (expected to be an OVM_StateTransitioner). We can revert here because // this would make the `run` itself invalid. + console.log('pre-auth'); require( // This method may return false during fraud proofs, but always returns true in L2 nodes' State Manager precompile. ovmStateManager.isAuthenticated(msg.sender), @@ -184,7 +185,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // Initialize the execution context, must be initialized before we perform any gas metering // or we'll throw a nuisance gas error. _initContext(_transaction); - // TEMPORARY: Gas metering is disabled for minnet. // // Check whether we need to start a new epoch, do so if necessary. // _checkNeedsNewEpoch(_transaction.timestamp); @@ -195,7 +195,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _resetContext(); return; } - + console.log('post valid gas limit'); // Check gas right before the call to get total gas consumed by OVM transaction. uint256 gasProvided = gasleft(); @@ -206,7 +206,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _transaction.data ); uint256 gasUsed = gasProvided - gasleft(); - + console.log('post omvcall'); // TEMPORARY: Gas metering is disabled for minnet. // // Update the cumulative gas based on the amount of gas used. // _updateCumulativeGas(gasUsed, _transaction.l1QueueOrigin); diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol index 98327b1ce..dadff1983 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol @@ -72,6 +72,9 @@ contract OVM_StateManager is iOVM_StateManager { modifier authenticated() { // owner is the State Transitioner console.log('caller: ', msg.sender); + console.log('owner:', owner); + console.log('ovmExecutionManager:', ovmExecutionManager); + console.log(msg.sender == owner || msg.sender == ovmExecutionManager); require( msg.sender == owner || msg.sender == ovmExecutionManager, "Function can only be called by authenticated addresses" diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol index 6b991fd07..70d025d39 100644 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -9,7 +9,7 @@ pragma solidity >0.5.0 <0.8.0; contract Helper_SimpleOvmDeployer { constructor(){ - console.log('Helper_SimpleOvmDeployer'); + console.log('deployed Helper_SimpleOvmDeployer'); } fallback() diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index b07fc08b0..d538568d9 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -3,7 +3,7 @@ import { deployContractCode } from '../../../helpers/utils' /* External Imports */ import { ethers } from 'hardhat' -import { Contract, ContractFactory, Signer } from 'ethers' +import { Contract, Signer } from 'ethers' import { smockit, MockContract, @@ -52,10 +52,8 @@ describe.only('OVM_ExecutionManager gas consumption', () => { let MOCK__OVM_DeployerWhitelist: MockContract let MODDABLE__STATE_MANAGER: ModifiableContract - // let MOCK__STATE_MANAGER: MockContract let AddressManager: Contract let gasMeasurement: GasMeasurement - let Factory__OVM_ExecutionManager: ContractFactory let OVM_ExecutionManager: Contract before(async () => { ;[wallet] = await ethers.getSigners() @@ -71,7 +69,7 @@ describe.only('OVM_ExecutionManager gas consumption', () => { OVM_SafetyChecker.address ) - // Deploy Safety Checker and register it with the Address Manager + // Deploy Safety Cache and register it with the Address Manager OVM_SafetyCache = await ( await ethers.getContractFactory('OVM_SafetyCache') ).deploy(AddressManager.address) @@ -91,24 +89,26 @@ describe.only('OVM_ExecutionManager gas consumption', () => { ) // Setup the EM - Factory__OVM_ExecutionManager = await ethers.getContractFactory( - 'OVM_ExecutionManager' - ) - OVM_ExecutionManager = ( - await Factory__OVM_ExecutionManager.deploy( + OVM_ExecutionManager = await ( + await ethers.getContractFactory('OVM_ExecutionManager') + ).deploy( AddressManager.address, DUMMY_GASMETERCONFIG, DUMMY_GLOBALCONTEXT ) - ).connect(wallet) + // .connect(wallet) + // Deploy GasMeasurement utility + gasMeasurement = new GasMeasurement() + await gasMeasurement.init(wallet) + // Setup the State Manger and modify it to allow execution to proceed MODDABLE__STATE_MANAGER = await ( await smoddit('OVM_StateManager') ).deploy( - NON_ZERO_ADDRESS + await wallet.getAddress() ) - + console.log('wallet address', await wallet.getAddress()) // Setup the SM to satisfy all the checks executed during EM.run() MODDABLE__STATE_MANAGER.smodify.set({ ovmExecutionManager: OVM_ExecutionManager.address @@ -137,15 +137,19 @@ describe.only('OVM_ExecutionManager gas consumption', () => { }, }) + + // MODDABLE__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) - await MODDABLE__STATE_MANAGER.smodify.puttestAndSetAccountLoaded(OVM_SafetyCache.address); - await MODDABLE__STATE_MANAGER.smodify.puttestAndSetAccountLoaded(MOCK__OVM_DeployerWhitelist.address); + console.log('testing and setting') + await MODDABLE__STATE_MANAGER.testAndSetAccountLoaded(OVM_SafetyCache.address); + await MODDABLE__STATE_MANAGER.testAndSetAccountLoaded(MOCK__OVM_DeployerWhitelist.address); // MODDABLE__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) // MODDABLE__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) - - // Deploy GasMeasurement utility - gasMeasurement = new GasMeasurement() - await gasMeasurement.init(wallet) + + MODDABLE__STATE_MANAGER.smodify.put({ + owner: gasMeasurement.GasMeasurementContract.address + }) + console.log('sm-owner ', await MODDABLE__STATE_MANAGER.owner()) }) describe('Measure cost of executing a very simple contract', async () => { @@ -160,14 +164,33 @@ describe.only('OVM_ExecutionManager gas consumption', () => { 10_000_000 ) DUMMY_TRANSACTION.entrypoint = targetContractAddress - MODDABLE__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( - targetContractAddress - ) + // MODDABLE__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( + // targetContractAddress + // ) + MODDABLE__STATE_MANAGER.smodify.set({ + accounts: { + [targetContractAddress]: { + nonce: 0, + codeHash: NON_NULL_BYTES32, + ethAddress: targetContractAddress, + }, + } + }) + console.log('target in sm', await MODDABLE__STATE_MANAGER.getAccountEthAddress(targetContractAddress)) + MODDABLE__STATE_MANAGER.smodify.set({ + ovmExecutionManager: OVM_ExecutionManager.address + }) }) - it('Gas benchmark: cost of run()', async () => { + it.only('Gas benchmark: cost of run()', async () => { // by setting the entrypoint to our minimal contract, and smocking the SM // we measure mostly the overhead of EM.run() + console.log('gm-address; ',gasMeasurement.GasMeasurementContract.address) + console.log('sm-owner: ', await MODDABLE__STATE_MANAGER.owner()) + MODDABLE__STATE_MANAGER.smodify.put({ + owner: gasMeasurement.GasMeasurementContract.address + }) + console.log('sm-owner: ', await MODDABLE__STATE_MANAGER.owner()) const gasCost = await gasMeasurement.getGasCost( OVM_ExecutionManager, 'run', @@ -185,17 +208,26 @@ describe.only('OVM_ExecutionManager gas consumption', () => { }) describe('Measure cost of deploying a simple contract', async () => { - let simpleDeployer: Contract + let Helper_SimpleDeployer: Contract before(async () => { // Deploy a simple OVM-safe contract that just deploys a another contract - simpleDeployer = await ( + Helper_SimpleDeployer = await ( await ethers.getContractFactory('Helper_SimpleOvmDeployer') ).deploy() - DUMMY_TRANSACTION.entrypoint = simpleDeployer.address + DUMMY_TRANSACTION.entrypoint = Helper_SimpleDeployer.address - MODDABLE__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( - simpleDeployer.address - ) + // MODDABLE__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( + // simpleDeployer.address + // ) + MODDABLE__STATE_MANAGER.smodify.set({ + accounts: { + [Helper_SimpleDeployer.address]: { + nonce: 0, + codeHash: NON_NULL_BYTES32, + ethAddress: Helper_SimpleDeployer.address, + }, + } + }) }) it('Gas Benchmark: un-chached contract deployment', async () => { From b9035a5cc1c66f5399f9647db4676b94f69b1cd0 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 8 Mar 2021 09:54:31 -0500 Subject: [PATCH 21/39] Save WIP status: debugging SM auth --- .../OVM/execution/OVM_ExecutionManager.sol | 4 +- .../OVM/execution/OVM_StateManager.sol | 6 + .../OVM_ExecutionManager.gas-spec.ts | 315 +++++++++--------- 3 files changed, 169 insertions(+), 156 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index aa337a783..3270c04ab 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -46,7 +46,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ********************************/ iOVM_SafetyCache internal ovmSafetyCache; - iOVM_SafetyChecker internal ovmSafetyChecker; + // iOVM_SafetyChecker internal ovmSafetyChecker; iOVM_StateManager internal ovmStateManager; @@ -182,6 +182,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { "Only authenticated addresses in ovmStateManager can call this function" ); + console.log('post-auth'); // Initialize the execution context, must be initialized before we perform any gas metering // or we'll throw a nuisance gas error. _initContext(_transaction); @@ -189,6 +190,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // // Check whether we need to start a new epoch, do so if necessary. // _checkNeedsNewEpoch(_transaction.timestamp); + console.log('post-init'); // Make sure the transaction's gas limit is valid. We don't revert here because we reserve // reverts for INVALID_STATE_ACCESS. if (_isValidGasLimit(_transaction.gasLimit, _transaction.l1QueueOrigin) == false) { diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol index dadff1983..e3d6825f3 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol @@ -71,6 +71,7 @@ contract OVM_StateManager is iOVM_StateManager { */ modifier authenticated() { // owner is the State Transitioner + console.log('authenticated modifier'); console.log('caller: ', msg.sender); console.log('owner:', owner); console.log('ovmExecutionManager:', ovmExecutionManager); @@ -101,6 +102,11 @@ contract OVM_StateManager is iOVM_StateManager { bool ) { + console.log('isauthenticated'); + console.log('_address: ', _address); + console.log('owner:', owner); + console.log('ovmExecutionManager:', ovmExecutionManager); + console.log(_address == owner || _address == ovmExecutionManager); return (_address == owner || _address == ovmExecutionManager); } diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index d538568d9..5476f33ea 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -3,9 +3,9 @@ import { deployContractCode } from '../../../helpers/utils' /* External Imports */ import { ethers } from 'hardhat' -import { Contract, Signer } from 'ethers' -import { - smockit, +import { Contract, ContractFactory, Signer } from 'ethers' +import { + smockit, MockContract, ModifiableContract, smoddit @@ -45,158 +45,68 @@ const DUMMY_TRANSACTION = { data: 0, } -describe.only('OVM_ExecutionManager gas consumption', () => { - let wallet: Signer - let OVM_SafetyChecker: Contract - let OVM_SafetyCache: Contract - let MOCK__OVM_DeployerWhitelist: MockContract - - let MODDABLE__STATE_MANAGER: ModifiableContract - let AddressManager: Contract - let gasMeasurement: GasMeasurement - let OVM_ExecutionManager: Contract - before(async () => { - ;[wallet] = await ethers.getSigners() - - AddressManager = await makeAddressManager() - - // Deploy Safety Checker and register it with the Address Manager - OVM_SafetyChecker = await ( - await ethers.getContractFactory('OVM_SafetyChecker') - ).deploy() - await AddressManager.setAddress( - 'OVM_SafetyChecker', - OVM_SafetyChecker.address - ) - - // Deploy Safety Cache and register it with the Address Manager - OVM_SafetyCache = await ( - await ethers.getContractFactory('OVM_SafetyCache') - ).deploy(AddressManager.address) - await AddressManager.setAddress( - 'OVM_SafetyCache', - OVM_SafetyCache.address - ) - - // Setup Mock Deployer Whitelist and register it with the Address Manager - MOCK__OVM_DeployerWhitelist = await smockit( - await ethers.getContractFactory('OVM_DeployerWhitelist') - ) - MOCK__OVM_DeployerWhitelist.smocked.isDeployerAllowed.will.return.with(true) - await AddressManager.setAddress( - 'OVM_DeployerWhitelist', - MOCK__OVM_DeployerWhitelist.address - ) - - // Setup the EM - OVM_ExecutionManager = await ( - await ethers.getContractFactory('OVM_ExecutionManager') - ).deploy( - AddressManager.address, - DUMMY_GASMETERCONFIG, - DUMMY_GLOBALCONTEXT - ) - // .connect(wallet) - - // Deploy GasMeasurement utility - gasMeasurement = new GasMeasurement() - await gasMeasurement.init(wallet) - - // Setup the State Manger and modify it to allow execution to proceed - MODDABLE__STATE_MANAGER = await ( - await smoddit('OVM_StateManager') - ).deploy( - await wallet.getAddress() - ) - console.log('wallet address', await wallet.getAddress()) - // Setup the SM to satisfy all the checks executed during EM.run() - MODDABLE__STATE_MANAGER.smodify.set({ - ovmExecutionManager: OVM_ExecutionManager.address - }) - console.log('ovmem', await MODDABLE__STATE_MANAGER.ovmExecutionManager()) - console.log('owner', await MODDABLE__STATE_MANAGER.owner()) - // MODDABLE__STATE_MANAGER.smocked.hasAccount.will.return.with(true) - MODDABLE__STATE_MANAGER.smodify.set({ - accounts: { - [OVM_SafetyCache.address]: { - nonce: 0, - codeHash: NON_NULL_BYTES32, - ethAddress: OVM_SafetyCache.address, - }, - // todo remove if unneeded - // [OVM_SafetyChecker.address]: { - // nonce: 0, - // codeHash: NON_NULL_BYTES32, - // ethAddress: OVM_SafetyChecker.address, - // }, - [MOCK__OVM_DeployerWhitelist.address]: { - nonce: 0, - codeHash: NON_NULL_BYTES32, - ethAddress: MOCK__OVM_DeployerWhitelist.address, - }, - - }, - }) - - - // MODDABLE__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) - console.log('testing and setting') - await MODDABLE__STATE_MANAGER.testAndSetAccountLoaded(OVM_SafetyCache.address); - await MODDABLE__STATE_MANAGER.testAndSetAccountLoaded(MOCK__OVM_DeployerWhitelist.address); - // MODDABLE__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) - // MODDABLE__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) - - MODDABLE__STATE_MANAGER.smodify.put({ - owner: gasMeasurement.GasMeasurementContract.address - }) - console.log('sm-owner ', await MODDABLE__STATE_MANAGER.owner()) - }) - - describe('Measure cost of executing a very simple contract', async () => { - +describe.only('OVM_ExecutionManager Benchmarks', () => { + describe('em.run() benchmark: executing a minimal contract', async () => { + let wallet: Signer + let Factory__OVM_ExecutionManager: ContractFactory + let OVM_ExecutionManager: Contract + let MOCK__STATE_MANAGER: MockContract + let AddressManager: Contract let targetContractAddress: string + let gasMeasurement: GasMeasurement before(async () => { - console.log('we here'); - // Deploy a simple OVM-safe contract which is just `STOP` + ;[wallet] = await ethers.getSigners() + Factory__OVM_ExecutionManager = await ethers.getContractFactory( + 'OVM_ExecutionManager' + ) + + // Deploy a simple contract that just returns successfully with no data targetContractAddress = await deployContractCode( - '00', + '60206001f3', wallet, 10_000_000 ) DUMMY_TRANSACTION.entrypoint = targetContractAddress - // MODDABLE__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( - // targetContractAddress - // ) - MODDABLE__STATE_MANAGER.smodify.set({ - accounts: { - [targetContractAddress]: { - nonce: 0, - codeHash: NON_NULL_BYTES32, - ethAddress: targetContractAddress, - }, - } - }) - console.log('target in sm', await MODDABLE__STATE_MANAGER.getAccountEthAddress(targetContractAddress)) - MODDABLE__STATE_MANAGER.smodify.set({ - ovmExecutionManager: OVM_ExecutionManager.address - }) + + AddressManager = await makeAddressManager() + + // deploy the state manager and mock it for the state transitioner + MOCK__STATE_MANAGER = await smockit( + await (await ethers.getContractFactory('OVM_StateManager')).deploy( + NON_ZERO_ADDRESS + ) + ) + + // Setup the SM to satisfy all the checks executed during EM.run() + MOCK__STATE_MANAGER.smocked.isAuthenticated.will.return.with(true) + MOCK__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( + targetContractAddress + ) + MOCK__STATE_MANAGER.smocked.hasAccount.will.return.with(true) + MOCK__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) + + await AddressManager.setAddress( + 'OVM_StateManagerFactory', + MOCK__STATE_MANAGER.address + ) + + gasMeasurement = new GasMeasurement() + await gasMeasurement.init(wallet) + OVM_ExecutionManager = ( + await Factory__OVM_ExecutionManager.deploy( + AddressManager.address, + DUMMY_GASMETERCONFIG, + DUMMY_GLOBALCONTEXT + ) + ).connect(wallet) }) - - it.only('Gas benchmark: cost of run()', async () => { - // by setting the entrypoint to our minimal contract, and smocking the SM - // we measure mostly the overhead of EM.run() - console.log('gm-address; ',gasMeasurement.GasMeasurementContract.address) - console.log('sm-owner: ', await MODDABLE__STATE_MANAGER.owner()) - MODDABLE__STATE_MANAGER.smodify.put({ - owner: gasMeasurement.GasMeasurementContract.address - }) - console.log('sm-owner: ', await MODDABLE__STATE_MANAGER.owner()) + it('Gas cost of run', async () => { const gasCost = await gasMeasurement.getGasCost( OVM_ExecutionManager, 'run', - [DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address] + [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] ) - console.log(` calculated gas cost of ${gasCost}`) + console.log(`calculated gas cost of ${gasCost}`) const benchmark: number = 226_516 expect(gasCost).to.be.lte(benchmark) @@ -206,19 +116,115 @@ describe.only('OVM_ExecutionManager gas consumption', () => { ) }) }) - - describe('Measure cost of deploying a simple contract', async () => { + describe('em.run() benchmark: deploying a minimal contract', async () => { let Helper_SimpleDeployer: Contract + let wallet: Signer + let OVM_SafetyChecker: Contract + let OVM_SafetyCache: Contract + let MOCK__OVM_DeployerWhitelist: MockContract + + let MODDABLE__STATE_MANAGER: ModifiableContract + let AddressManager: Contract + let gasMeasurement: GasMeasurement + let OVM_ExecutionManager: Contract before(async () => { - // Deploy a simple OVM-safe contract that just deploys a another contract + ;[wallet] = await ethers.getSigners() + + AddressManager = await makeAddressManager() + + // Deploy Safety Checker and register it with the Address Manager + OVM_SafetyChecker = await ( + await ethers.getContractFactory('OVM_SafetyChecker') + ).deploy() + await AddressManager.setAddress( + 'OVM_SafetyChecker', + OVM_SafetyChecker.address + ) + + // Deploy Safety Cache and register it with the Address Manager + OVM_SafetyCache = await ( + await ethers.getContractFactory('OVM_SafetyCache') + ).deploy(AddressManager.address) + await AddressManager.setAddress( + 'OVM_SafetyCache', + OVM_SafetyCache.address + ) + + // Setup Mock Deployer Whitelist and register it with the Address Manager + MOCK__OVM_DeployerWhitelist = await smockit( + await ethers.getContractFactory('OVM_DeployerWhitelist') + ) + MOCK__OVM_DeployerWhitelist.smocked.isDeployerAllowed.will.return.with(true) + await AddressManager.setAddress( + 'OVM_DeployerWhitelist', + MOCK__OVM_DeployerWhitelist.address + ) + + // Setup the EM + OVM_ExecutionManager = await ( + await ethers.getContractFactory('OVM_ExecutionManager') + ).deploy( + AddressManager.address, + DUMMY_GASMETERCONFIG, + DUMMY_GLOBALCONTEXT + )// .connect(wallet) + + // Deploy GasMeasurement utility + gasMeasurement = new GasMeasurement() + await gasMeasurement.init(wallet) + + // Setup the State Manger and modify it to allow execution to proceed + MODDABLE__STATE_MANAGER = await ( + await smoddit('OVM_StateManager') + ).deploy( + await wallet.getAddress() + ) + console.log('wallet address:', await wallet.getAddress()) + // Setup the SM to satisfy all the checks executed during EM.run() + MODDABLE__STATE_MANAGER.smodify.set({ + ovmExecutionManager: OVM_ExecutionManager.address + }) + console.log('stateManager.ovmExecutionManager:', await MODDABLE__STATE_MANAGER.ovmExecutionManager()) + console.log('stateManager.owner:', await MODDABLE__STATE_MANAGER.owner()) + // MODDABLE__STATE_MANAGER.smocked.hasAccount.will.return.with(true) + MODDABLE__STATE_MANAGER.smodify.set({ + accounts: { + [OVM_SafetyCache.address]: { + nonce: 0, + codeHash: NON_NULL_BYTES32, + ethAddress: OVM_SafetyCache.address, + }, + // todo remove if unneeded + // [OVM_SafetyChecker.address]: { + // nonce: 0, + // codeHash: NON_NULL_BYTES32, + // ethAddress: OVM_SafetyChecker.address, + // }, + [MOCK__OVM_DeployerWhitelist.address]: { + nonce: 0, + codeHash: NON_NULL_BYTES32, + ethAddress: MOCK__OVM_DeployerWhitelist.address, + }, + + }, + }) + + console.log('testing and setting') + await MODDABLE__STATE_MANAGER.testAndSetAccountLoaded(OVM_SafetyCache.address); + await MODDABLE__STATE_MANAGER.testAndSetAccountLoaded(MOCK__OVM_DeployerWhitelist.address); + await MODDABLE__STATE_MANAGER.setExecutionManager(OVM_ExecutionManager.address) + MODDABLE__STATE_MANAGER.smodify.set({ + owner: gasMeasurement.GasMeasurementContract.address + }) // @flag: this doesn't seem to actually modify the owner + console.log('sm-owner ', await MODDABLE__STATE_MANAGER.owner()) + + // Deploy a simple OVM-safe contract that just deploys another contract Helper_SimpleDeployer = await ( await ethers.getContractFactory('Helper_SimpleOvmDeployer') ).deploy() DUMMY_TRANSACTION.entrypoint = Helper_SimpleDeployer.address - // MODDABLE__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( - // simpleDeployer.address - // ) + MODDABLE__STATE_MANAGER.smodify.set({ accounts: { [Helper_SimpleDeployer.address]: { @@ -231,6 +237,11 @@ describe.only('OVM_ExecutionManager gas consumption', () => { }) it('Gas Benchmark: un-chached contract deployment', async () => { + MODDABLE__STATE_MANAGER.smodify.set({ + ovmExecutionManager: OVM_ExecutionManager.address + }) + console.log('ovmem', await MODDABLE__STATE_MANAGER.ovmExecutionManager()) + console.log('ovmem', OVM_ExecutionManager.address) const gasCost = await gasMeasurement.getGasCost( OVM_ExecutionManager, 'run', @@ -262,10 +273,4 @@ describe.only('OVM_ExecutionManager gas consumption', () => { ) }) }) - describe.skip('Measure cost of deploying a larger contract', async () => { - it('Benchmark un-chached contract deployment', async () => { - }) - it('Gas benchmark: deploying a cached contract', async () => { - }) - }) }) From 3e29b15f2fac2d2e379616f6570d3210da5578cf Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 8 Mar 2021 16:30:49 -0500 Subject: [PATCH 22/39] Simplify tests --- .../OVM_ExecutionManager.gas-spec.ts | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 5476f33ea..1ea499813 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -236,20 +236,13 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { }) }) - it('Gas Benchmark: un-chached contract deployment', async () => { - MODDABLE__STATE_MANAGER.smodify.set({ - ovmExecutionManager: OVM_ExecutionManager.address - }) - console.log('ovmem', await MODDABLE__STATE_MANAGER.ovmExecutionManager()) - console.log('ovmem', OVM_ExecutionManager.address) - const gasCost = await gasMeasurement.getGasCost( - OVM_ExecutionManager, - 'run', - [DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address] - ) + it('Gas Benchmark: un-cached contract deployment', async () => { + const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address) + await tx.wait() + const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 3_488_629 + const benchmark: number = 217758 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, @@ -258,14 +251,12 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { }) it('Gas Benchmark: deploying a cached contract', async () => { - const gasCost = await gasMeasurement.getGasCost( - OVM_ExecutionManager, - 'run', - [DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address] - ) + const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address) + await tx.wait() + const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 226_516 + const benchmark: number = 217758 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, From 63fece3f8a3ac54e764bb63c04f6b2747dcfe5a6 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 8 Mar 2021 20:23:40 -0500 Subject: [PATCH 23/39] Save with interesting bug --- .../OVM/execution/OVM_ExecutionManager.sol | 17 ++++--------- .../OVM/execution/OVM_StateManager.sol | 12 ---------- .../test-helpers/Helper_SimpleOvmDeployer.sol | 13 ++++------ .../OVM_ExecutionManager.gas-spec.ts | 24 +++++-------------- 4 files changed, 16 insertions(+), 50 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index 3270c04ab..ea2ff920a 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -5,7 +5,6 @@ pragma experimental ABIEncoderV2; import "hardhat/console.sol"; - /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; @@ -89,7 +88,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { public Lib_AddressResolver(_libAddressManager) { - console.log('constructor'); ovmSafetyCache = iOVM_SafetyCache(resolve("OVM_SafetyCache")); gasMeterConfig = _gasMeterConfig; globalContext = _globalContext; @@ -167,6 +165,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { override public { + console.log('txContext.ovmNumber:',transactionContext.ovmNUMBER); require(transactionContext.ovmNUMBER == 0, "Only be callable at the start of a transaction"); // Store our OVM_StateManager instance (significantly easier than attempting to pass the // address around in calldata). @@ -175,14 +174,12 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // Make sure this function can't be called by anyone except the owner of the // OVM_StateManager (expected to be an OVM_StateTransitioner). We can revert here because // this would make the `run` itself invalid. - console.log('pre-auth'); require( // This method may return false during fraud proofs, but always returns true in L2 nodes' State Manager precompile. ovmStateManager.isAuthenticated(msg.sender), "Only authenticated addresses in ovmStateManager can call this function" ); - console.log('post-auth'); // Initialize the execution context, must be initialized before we perform any gas metering // or we'll throw a nuisance gas error. _initContext(_transaction); @@ -190,14 +187,12 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // // Check whether we need to start a new epoch, do so if necessary. // _checkNeedsNewEpoch(_transaction.timestamp); - console.log('post-init'); // Make sure the transaction's gas limit is valid. We don't revert here because we reserve // reverts for INVALID_STATE_ACCESS. if (_isValidGasLimit(_transaction.gasLimit, _transaction.l1QueueOrigin) == false) { _resetContext(); return; } - console.log('post valid gas limit'); // Check gas right before the call to get total gas consumed by OVM transaction. uint256 gasProvided = gasleft(); @@ -208,14 +203,13 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _transaction.data ); uint256 gasUsed = gasProvided - gasleft(); - console.log('post omvcall'); // TEMPORARY: Gas metering is disabled for minnet. // // Update the cumulative gas based on the amount of gas used. // _updateCumulativeGas(gasUsed, _transaction.l1QueueOrigin); // Wipe the execution context. _resetContext(); - + console.log('reset context', transactionContext.ovmNUMBER); // Reset the ovmStateManager. ovmStateManager = iOVM_StateManager(address(0)); } @@ -818,7 +812,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _revertWithFlag(RevertFlag.CREATE_COLLISION); } - console.log('pre-check'); // Check the creation bytecode against the Safety Cache and Safety Checker. if (ovmSafetyCache.checkAndRegisterSafeBytecode(_bytecode) == false) { _revertWithFlag(RevertFlag.UNSAFE_BYTECODE); @@ -1061,6 +1054,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // parent EVM message. This behavior is necessary because INVALID_STATE_ACCESS must // halt any further transaction execution that could impact the execution result. if (flag == RevertFlag.INVALID_STATE_ACCESS) { + console.log("INVALID_STATE_ACCESS"); _revertWithFlag(flag); } @@ -1186,9 +1180,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ) { _checkAccountLoad(_address); - address gotten = ovmStateManager.getAccountEthAddress(_address); - // console.log('_getAccountEthAddress', _address, gotten); - return gotten; + return ovmStateManager.getAccountEthAddress(_address); } /** @@ -1534,6 +1526,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _data ); + console.log('revertflag', uint8(_flag)); assembly { revert(add(revertdata, 0x20), mload(revertdata)) } diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol index e3d6825f3..25f056690 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol @@ -2,8 +2,6 @@ pragma solidity >0.5.0 <0.8.0; pragma experimental ABIEncoderV2; -import "hardhat/console.sol"; - /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; @@ -71,11 +69,6 @@ contract OVM_StateManager is iOVM_StateManager { */ modifier authenticated() { // owner is the State Transitioner - console.log('authenticated modifier'); - console.log('caller: ', msg.sender); - console.log('owner:', owner); - console.log('ovmExecutionManager:', ovmExecutionManager); - console.log(msg.sender == owner || msg.sender == ovmExecutionManager); require( msg.sender == owner || msg.sender == ovmExecutionManager, "Function can only be called by authenticated addresses" @@ -102,11 +95,6 @@ contract OVM_StateManager is iOVM_StateManager { bool ) { - console.log('isauthenticated'); - console.log('_address: ', _address); - console.log('owner:', owner); - console.log('ovmExecutionManager:', ovmExecutionManager); - console.log(_address == owner || _address == ovmExecutionManager); return (_address == owner || _address == ovmExecutionManager); } diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol index 70d025d39..755f3097d 100644 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -6,16 +6,13 @@ import "hardhat/console.sol"; pragma solidity >0.5.0 <0.8.0; -contract Helper_SimpleOvmDeployer { - - constructor(){ - console.log('deployed Helper_SimpleOvmDeployer'); - } - +contract Helper_SimpleOvmDeployer { fallback() external { - Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), "00"); - console.log('deployed with bytecode: 0x00'); + console.log('deploying a contract with bytecode: 0x00'); + bytes memory initCode = "600D380380600D6000396000f300"; + address addr = Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), initCode); + console.log(addr); } } diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 1ea499813..6523a44b5 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -106,7 +106,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { 'run', [DUMMY_TRANSACTION, MOCK__STATE_MANAGER.address] ) - console.log(`calculated gas cost of ${gasCost}`) + console.log(` calculated gas cost of ${gasCost}`) const benchmark: number = 226_516 expect(gasCost).to.be.lte(benchmark) @@ -179,14 +179,12 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { ).deploy( await wallet.getAddress() ) - console.log('wallet address:', await wallet.getAddress()) + // Setup the SM to satisfy all the checks executed during EM.run() MODDABLE__STATE_MANAGER.smodify.set({ ovmExecutionManager: OVM_ExecutionManager.address }) - console.log('stateManager.ovmExecutionManager:', await MODDABLE__STATE_MANAGER.ovmExecutionManager()) - console.log('stateManager.owner:', await MODDABLE__STATE_MANAGER.owner()) - // MODDABLE__STATE_MANAGER.smocked.hasAccount.will.return.with(true) + MODDABLE__STATE_MANAGER.smodify.set({ accounts: { [OVM_SafetyCache.address]: { @@ -194,12 +192,6 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { codeHash: NON_NULL_BYTES32, ethAddress: OVM_SafetyCache.address, }, - // todo remove if unneeded - // [OVM_SafetyChecker.address]: { - // nonce: 0, - // codeHash: NON_NULL_BYTES32, - // ethAddress: OVM_SafetyChecker.address, - // }, [MOCK__OVM_DeployerWhitelist.address]: { nonce: 0, codeHash: NON_NULL_BYTES32, @@ -209,14 +201,9 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { }, }) - console.log('testing and setting') await MODDABLE__STATE_MANAGER.testAndSetAccountLoaded(OVM_SafetyCache.address); await MODDABLE__STATE_MANAGER.testAndSetAccountLoaded(MOCK__OVM_DeployerWhitelist.address); await MODDABLE__STATE_MANAGER.setExecutionManager(OVM_ExecutionManager.address) - MODDABLE__STATE_MANAGER.smodify.set({ - owner: gasMeasurement.GasMeasurementContract.address - }) // @flag: this doesn't seem to actually modify the owner - console.log('sm-owner ', await MODDABLE__STATE_MANAGER.owner()) // Deploy a simple OVM-safe contract that just deploys another contract Helper_SimpleDeployer = await ( @@ -242,7 +229,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 217758 + const benchmark: number = 272_527 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, @@ -251,12 +238,13 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { }) it('Gas Benchmark: deploying a cached contract', async () => { + // run the exact same flow as the previous. This time the Safety Cache should recognize the string. const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address) await tx.wait() const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 217758 + const benchmark: number = 272_527 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, From c85579ded4a32a47c5e026fe329640d6d677e4c0 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Mon, 8 Mar 2021 20:32:56 -0500 Subject: [PATCH 24/39] Save with interesting bug --- .../OVM/execution/OVM_ExecutionManager.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index ea2ff920a..7ff7a0b01 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -919,9 +919,10 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { address _created ) { + console.log("Address: %s, nonce: %s", ovmADDRESS(), _getAccountNonce(ovmADDRESS())); // We always update the nonce of the creating account, even if the creation fails. _setAccountNonce(ovmADDRESS(), _getAccountNonce(ovmADDRESS()) + 1); - + // We're stepping into a CREATE or CREATE2, so we need to update ADDRESS to point // to the contract's associated address and CALLER to point to the previous ADDRESS. MessageContext memory nextMessageContext = messageContext; @@ -1161,7 +1162,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { returns ( uint256 _nonce ) - { + { _checkAccountLoad(_address); return ovmStateManager.getAccountNonce(_address); } From 2f830e297451e0b86b7a7c171bbd37c61f34ff7b Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 09:48:29 -0500 Subject: [PATCH 25/39] working and heavily annotated with console.log() --- .../OVM/execution/OVM_ExecutionManager.sol | 39 +++++------ .../OVM/execution/OVM_SafetyCache.sol | 3 +- .../OVM/execution/OVM_StateManager.sol | 3 + .../Lib_SafeExecutionManagerWrapper.sol | 5 ++ .../test-helpers/Helper_SimpleOvmDeployer.sol | 2 +- .../OVM_ExecutionManager.gas-spec.ts | 70 ++++++++++--------- 6 files changed, 65 insertions(+), 57 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index 7ff7a0b01..21b198c5c 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -21,7 +21,6 @@ import { iOVM_SafetyChecker } from "../../iOVM/execution/iOVM_SafetyChecker.sol" /* Contract Imports */ import { OVM_ECDSAContractAccount } from "../accounts/OVM_ECDSAContractAccount.sol"; import { OVM_ProxyEOA } from "../accounts/OVM_ProxyEOA.sol"; -import { OVM_DeployerWhitelist } from "../precompiles/OVM_DeployerWhitelist.sol"; /** * @title OVM_ExecutionManager @@ -381,19 +380,22 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { address _contract ) { + console.log('ovmCreate 1'); // Creator is always the current ADDRESS. address creator = ovmADDRESS(); // Check that the deployer is whitelisted, or // that arbitrary contract deployment has been enabled. - _checkDeployerAllowed(creator); + // @note: makes a call to ovmCall deployer-whitelist + // failure here (due to false hasAccount) results in un-reset context + _checkDeployerAllowed(creator); // Generate the correct CREATE address. address contractAddress = Lib_EthUtils.getAddressForCREATE( creator, _getAccountNonce(creator) ); - + console.log('ovmCreate 2'); return _createContract( contractAddress, _bytecode @@ -797,12 +799,14 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { override public { + console.log('safeCreate'); // Since this function is public, anyone can attempt to directly call it. We need to make // sure that the OVM_ExecutionManager itself is the only party that can actually try to // call this function. if (msg.sender != address(this)) { return; } + console.log('safeCreate 2', _address); // We need to be sure that the user isn't trying to use a contract creation to overwrite // some existing contract. On L1, users will prove that no contract exists at the address @@ -811,15 +815,20 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { if (_hasEmptyAccount(_address) == false) { _revertWithFlag(RevertFlag.CREATE_COLLISION); } + + console.log('safeCreate 3'); + console.logBytes( _bytecode); // Check the creation bytecode against the Safety Cache and Safety Checker. if (ovmSafetyCache.checkAndRegisterSafeBytecode(_bytecode) == false) { _revertWithFlag(RevertFlag.UNSAFE_BYTECODE); } + console.log('safeCreate 4'); + console.log('pre-initpending', _address); // We always need to initialize the contract with the default account values. _initPendingAccount(_address); - + console.log('pre-evmCreate'); // Actually deploy the contract and retrieve its address. This step is hiding a lot of // complexity because we need to ensure that contract creation *never* reverts by itself. // We cover this partially by storing a revert flag and returning (instead of reverting) @@ -984,7 +993,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { address codeContractAddress = uint(_contract) < 100 ? _contract - : _getAccountEthAddress(_contract); + : _getAccountEthAddress(_contract); // @flag reverts here with invalid state access when deployerWhitelist is not in SM return _handleExternalInteraction( _nextMessageContext, @@ -1101,23 +1110,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { * Internal Functions: State Manipulation * ******************************************/ - /** - * Checks whether an account exists within the OVM_StateManager. - * @param _address Address of the account to check. - * @return _exists Whether or not the account exists. - */ - function _hasAccount( - address _address - ) - internal - returns ( - bool _exists - ) - { - _checkAccountLoad(_address); - return ovmStateManager.hasAccount(_address); - } - /** * Checks whether a known empty account exists within the OVM_StateManager. * @param _address Address of the account to check. @@ -1163,6 +1155,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { uint256 _nonce ) { + console.log('getAccountNonce: %s' ,_address); _checkAccountLoad(_address); return ovmStateManager.getAccountNonce(_address); } @@ -1180,6 +1173,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { address _ethAddress ) { + console.log('_getAccountEthAddress'); _checkAccountLoad(_address); return ovmStateManager.getAccountEthAddress(_address); } @@ -1283,6 +1277,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _revertWithFlag(RevertFlag.OUT_OF_GAS); } + console.log("_checkAccountLoad"); // See `_checkContractStorageLoad` for more information. if (ovmStateManager.hasAccount(_address) == false) { _revertWithFlag(RevertFlag.INVALID_STATE_ACCESS); diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol index 674796c2c..eb84e3f30 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol @@ -75,7 +75,8 @@ contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { bytes32 codehash = keccak256(abi.encode(_code)); console.log("codehash: "); console.logBytes32(codehash); - console.log(uint(codehash)); + console.log("code: "); + console.logBytes(_code); if(isSafeCodehash[codehash] == true) { return true; } diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol index 25f056690..cb8bc61a3 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol @@ -2,6 +2,8 @@ pragma solidity >0.5.0 <0.8.0; pragma experimental ABIEncoderV2; +import "hardhat/console.sol"; + /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; @@ -177,6 +179,7 @@ contract OVM_StateManager is iOVM_StateManager { bool ) { + console.log('hasAccount', accounts[_address].codeHash != bytes32(0), _address); return accounts[_address].codeHash != bytes32(0); } diff --git a/contracts/optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol b/contracts/optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol index ea0ff707c..bca75fdbb 100644 --- a/contracts/optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol +++ b/contracts/optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol @@ -10,6 +10,9 @@ pragma solidity >0.5.0 <0.8.0; * Compiler used: solc * Runtime target: OVM */ + +import "hardhat/console.sol"; + library Lib_SafeExecutionManagerWrapper { /********************** @@ -342,6 +345,8 @@ library Lib_SafeExecutionManagerWrapper { bytes memory _returndata ) { + console.log('calldata:'); + console.logBytes(_calldata); address ovmExecutionManager = msg.sender; ( bool success, diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol index 755f3097d..0ef90f1fc 100644 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -11,7 +11,7 @@ contract Helper_SimpleOvmDeployer { external { console.log('deploying a contract with bytecode: 0x00'); - bytes memory initCode = "600D380380600D6000396000f300"; + bytes memory initCode = hex'600D380380600D6000396000f300'; address addr = Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), initCode); console.log(addr); } diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 6523a44b5..a3dad6798 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -2,6 +2,7 @@ import { expect } from '../../../setup' import { deployContractCode } from '../../../helpers/utils' /* External Imports */ +import { BigNumber } from 'ethers' import { ethers } from 'hardhat' import { Contract, ContractFactory, Signer } from 'ethers' import { @@ -17,6 +18,7 @@ import { NON_ZERO_ADDRESS, NON_NULL_BYTES32, GasMeasurement, + DUMMY_BYTES32 } from '../../../helpers' const DUMMY_GASMETERCONFIG = { @@ -167,7 +169,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { AddressManager.address, DUMMY_GASMETERCONFIG, DUMMY_GLOBALCONTEXT - )// .connect(wallet) + ) // Deploy GasMeasurement utility gasMeasurement = new GasMeasurement() @@ -181,49 +183,46 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { ) // Setup the SM to satisfy all the checks executed during EM.run() - MODDABLE__STATE_MANAGER.smodify.set({ - ovmExecutionManager: OVM_ExecutionManager.address - }) - - MODDABLE__STATE_MANAGER.smodify.set({ - accounts: { - [OVM_SafetyCache.address]: { - nonce: 0, - codeHash: NON_NULL_BYTES32, - ethAddress: OVM_SafetyCache.address, - }, - [MOCK__OVM_DeployerWhitelist.address]: { - nonce: 0, - codeHash: NON_NULL_BYTES32, - ethAddress: MOCK__OVM_DeployerWhitelist.address, - }, - + await MODDABLE__STATE_MANAGER.putAccount( + "0x4200000000000000000000000000000000000002", + { + nonce: BigNumber.from(123), + balance: BigNumber.from(456), + storageRoot: DUMMY_BYTES32[0], + codeHash: DUMMY_BYTES32[1], + ethAddress: MOCK__OVM_DeployerWhitelist.address, }, - }) - - await MODDABLE__STATE_MANAGER.testAndSetAccountLoaded(OVM_SafetyCache.address); - await MODDABLE__STATE_MANAGER.testAndSetAccountLoaded(MOCK__OVM_DeployerWhitelist.address); + ); await MODDABLE__STATE_MANAGER.setExecutionManager(OVM_ExecutionManager.address) - + + // Deploy a simple OVM-safe contract that just deploys another contract Helper_SimpleDeployer = await ( await ethers.getContractFactory('Helper_SimpleOvmDeployer') ).deploy() DUMMY_TRANSACTION.entrypoint = Helper_SimpleDeployer.address + console.log("Helper_SimpleDeployer.address:" , Helper_SimpleDeployer.address); + - - MODDABLE__STATE_MANAGER.smodify.set({ - accounts: { - [Helper_SimpleDeployer.address]: { - nonce: 0, - codeHash: NON_NULL_BYTES32, - ethAddress: Helper_SimpleDeployer.address, - }, - } - }) + await MODDABLE__STATE_MANAGER.putAccount( + Helper_SimpleDeployer.address, + { + nonce: BigNumber.from(123), + balance: BigNumber.from(456), + storageRoot: DUMMY_BYTES32[0], + codeHash: DUMMY_BYTES32[1], + ethAddress: Helper_SimpleDeployer.address, + }, + ) + }) it('Gas Benchmark: un-cached contract deployment', async () => { + // Set destination for first contract deployment + await MODDABLE__STATE_MANAGER.putEmptyAccount( + "0xf7a70a9ed665630eaaf9f7b40b71f01cbf65f73f" + ) + const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address) await tx.wait() const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed @@ -238,6 +237,11 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { }) it('Gas Benchmark: deploying a cached contract', async () => { + // Set destination for second contract deployment + await MODDABLE__STATE_MANAGER.putEmptyAccount( + "0xd236d314fd67606dddb3885f1330cf9bd3c8dbea" + ) + // run the exact same flow as the previous. This time the Safety Cache should recognize the string. const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address) await tx.wait() From 74101a8f77f6757ef3b0392327f6f415dd6d1b83 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 11:10:15 -0500 Subject: [PATCH 26/39] Tests working --- .../OVM/execution/OVM_ExecutionManager.sol | 39 ++++++------------- .../OVM/execution/OVM_SafetyCache.sol | 8 ---- .../OVM/execution/OVM_StateManager.sol | 3 -- .../Lib_SafeExecutionManagerWrapper.sol | 5 --- .../test-helpers/Helper_SimpleOvmDeployer.sol | 8 ++-- .../OVM_ExecutionManager.gas-spec.ts | 4 +- 6 files changed, 16 insertions(+), 51 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index d5036ea2e..42c0c858d 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -3,8 +3,6 @@ pragma solidity >0.5.0 <0.8.0; pragma experimental ABIEncoderV2; -import "hardhat/console.sol"; - /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; @@ -31,7 +29,7 @@ import { OVM_ProxyEOA } from "../accounts/OVM_ProxyEOA.sol"; * transaction on L2. * For each context-dependent EVM operation the EM has a function which implements a corresponding * OVM operation, which will read state from the State Manager contract. - * The EM relies on the Safety Cache and Checker to verify that code deployed to Layer 2 does not contain any + * The EM relies on the Safety Checker to verify that code deployed to Layer 2 does not contain any * context-dependent operations. * * Compiler used: solc @@ -44,7 +42,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { ********************************/ iOVM_SafetyCache internal ovmSafetyCache; - // iOVM_SafetyChecker internal ovmSafetyChecker; iOVM_StateManager internal ovmStateManager; @@ -163,7 +160,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { override public { - console.log('txContext.ovmNumber:',transactionContext.ovmNUMBER); require(transactionContext.ovmNUMBER == 0, "Only be callable at the start of a transaction"); // Store our OVM_StateManager instance (significantly easier than attempting to pass the // address around in calldata). @@ -181,6 +177,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // Initialize the execution context, must be initialized before we perform any gas metering // or we'll throw a nuisance gas error. _initContext(_transaction); + // TEMPORARY: Gas metering is disabled for minnet. // // Check whether we need to start a new epoch, do so if necessary. // _checkNeedsNewEpoch(_transaction.timestamp); @@ -191,6 +188,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _resetContext(); return; } + // Check gas right before the call to get total gas consumed by OVM transaction. uint256 gasProvided = gasleft(); @@ -201,13 +199,14 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _transaction.data ); uint256 gasUsed = gasProvided - gasleft(); + // TEMPORARY: Gas metering is disabled for minnet. // // Update the cumulative gas based on the amount of gas used. // _updateCumulativeGas(gasUsed, _transaction.l1QueueOrigin); // Wipe the execution context. _resetContext(); - console.log('reset context', transactionContext.ovmNUMBER); + // Reset the ovmStateManager. ovmStateManager = iOVM_StateManager(address(0)); } @@ -379,22 +378,19 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { address _contract ) { - console.log('ovmCreate 1'); // Creator is always the current ADDRESS. address creator = ovmADDRESS(); // Check that the deployer is whitelisted, or // that arbitrary contract deployment has been enabled. - // @note: makes a call to ovmCall deployer-whitelist - // failure here (due to false hasAccount) results in un-reset context - _checkDeployerAllowed(creator); + _checkDeployerAllowed(creator); // Generate the correct CREATE address. address contractAddress = Lib_EthUtils.getAddressForCREATE( creator, _getAccountNonce(creator) ); - console.log('ovmCreate 2'); + return _createContract( contractAddress, _bytecode @@ -799,14 +795,12 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { override public { - console.log('safeCreate'); // Since this function is public, anyone can attempt to directly call it. We need to make // sure that the OVM_ExecutionManager itself is the only party that can actually try to // call this function. if (msg.sender != address(this)) { return; } - console.log('safeCreate 2', _address); // We need to be sure that the user isn't trying to use a contract creation to overwrite // some existing contract. On L1, users will prove that no contract exists at the address @@ -815,20 +809,15 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { if (_hasEmptyAccount(_address) == false) { _revertWithFlag(RevertFlag.CREATE_COLLISION); } - - console.log('safeCreate 3'); - console.logBytes( _bytecode); // Check the creation bytecode against the Safety Cache and Safety Checker. if (ovmSafetyCache.checkAndRegisterSafeBytecode(_bytecode) == false) { _revertWithFlag(RevertFlag.UNSAFE_BYTECODE); } - console.log('safeCreate 4'); - console.log('pre-initpending', _address); // We always need to initialize the contract with the default account values. _initPendingAccount(_address); - console.log('pre-evmCreate'); + // Actually deploy the contract and retrieve its address. This step is hiding a lot of // complexity because we need to ensure that contract creation *never* reverts by itself. // We cover this partially by storing a revert flag and returning (instead of reverting) @@ -928,10 +917,9 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { address _created ) { - console.log("Address: %s, nonce: %s", ovmADDRESS(), _getAccountNonce(ovmADDRESS())); // We always update the nonce of the creating account, even if the creation fails. _setAccountNonce(ovmADDRESS(), _getAccountNonce(ovmADDRESS()) + 1); - + // We're stepping into a CREATE or CREATE2, so we need to update ADDRESS to point // to the contract's associated address and CALLER to point to the previous ADDRESS. MessageContext memory nextMessageContext = messageContext; @@ -993,7 +981,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { address codeContractAddress = uint(_contract) < 100 ? _contract - : _getAccountEthAddress(_contract); // @flag reverts here with invalid state access when deployerWhitelist is not in SM + : _getAccountEthAddress(_contract); return _handleExternalInteraction( _nextMessageContext, @@ -1064,7 +1052,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // parent EVM message. This behavior is necessary because INVALID_STATE_ACCESS must // halt any further transaction execution that could impact the execution result. if (flag == RevertFlag.INVALID_STATE_ACCESS) { - console.log("INVALID_STATE_ACCESS"); _revertWithFlag(flag); } @@ -1154,8 +1141,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { returns ( uint256 _nonce ) - { - console.log('getAccountNonce: %s' ,_address); + { _checkAccountLoad(_address); return ovmStateManager.getAccountNonce(_address); } @@ -1173,7 +1159,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { address _ethAddress ) { - console.log('_getAccountEthAddress'); _checkAccountLoad(_address); return ovmStateManager.getAccountEthAddress(_address); } @@ -1277,7 +1262,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _revertWithFlag(RevertFlag.OUT_OF_GAS); } - console.log("_checkAccountLoad"); // See `_checkContractStorageLoad` for more information. if (ovmStateManager.hasAccount(_address) == false) { _revertWithFlag(RevertFlag.INVALID_STATE_ACCESS); @@ -1522,7 +1506,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { _data ); - console.log('revertflag', uint8(_flag)); assembly { revert(add(revertdata, 0x20), mload(revertdata)) } diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol index eb84e3f30..099434ed5 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol @@ -10,9 +10,6 @@ import { iOVM_SafetyCache } from "../../iOVM/execution/iOVM_SafetyCache.sol"; /* Inherited Interface Imports */ import { iOVM_SafetyChecker } from "../../iOVM/execution/iOVM_SafetyChecker.sol"; -import "hardhat/console.sol"; - - /** * @title OVM_SafetyCache * @dev This contract implements a simple registry for caching the hash of any bytecode strings which have @@ -73,16 +70,11 @@ contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { bool ) { bytes32 codehash = keccak256(abi.encode(_code)); - console.log("codehash: "); - console.logBytes32(codehash); - console.log("code: "); - console.logBytes(_code); if(isSafeCodehash[codehash] == true) { return true; } bool safe = ovmSafetyChecker.isBytecodeSafe(_code); - console.log("safe: ", safe); if(safe) { isSafeCodehash[codehash] = true; } diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol index c096b3517..2d8a95bc1 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol @@ -2,8 +2,6 @@ pragma solidity >0.5.0 <0.8.0; pragma experimental ABIEncoderV2; -import "hardhat/console.sol"; - /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; @@ -178,7 +176,6 @@ contract OVM_StateManager is iOVM_StateManager { bool ) { - console.log('hasAccount', accounts[_address].codeHash != bytes32(0), _address); return accounts[_address].codeHash != bytes32(0); } diff --git a/contracts/optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol b/contracts/optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol index bca75fdbb..ea0ff707c 100644 --- a/contracts/optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol +++ b/contracts/optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol @@ -10,9 +10,6 @@ pragma solidity >0.5.0 <0.8.0; * Compiler used: solc * Runtime target: OVM */ - -import "hardhat/console.sol"; - library Lib_SafeExecutionManagerWrapper { /********************** @@ -345,8 +342,6 @@ library Lib_SafeExecutionManagerWrapper { bytes memory _returndata ) { - console.log('calldata:'); - console.logBytes(_calldata); address ovmExecutionManager = msg.sender; ( bool success, diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol index 0ef90f1fc..bb58453f3 100644 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -1,18 +1,16 @@ // SPDX-License-Identifier: UNLICENSED // SPDX-License-Identifier: MIT import { Lib_SafeExecutionManagerWrapper } from "../optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol"; -import "hardhat/console.sol"; - pragma solidity >0.5.0 <0.8.0; -contract Helper_SimpleOvmDeployer { +contract Helper_SimpleOvmDeployer { + fallback() external { - console.log('deploying a contract with bytecode: 0x00'); + // the resulting deployed bytecode is 0x00 bytes memory initCode = hex'600D380380600D6000396000f300'; address addr = Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), initCode); - console.log(addr); } } diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index a3dad6798..ce7b255ee 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -228,7 +228,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 272_527 + const benchmark: number = 581_062 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, @@ -248,7 +248,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 272_527 + const benchmark: number = 414_398 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, From c20948274706d1e66c47aab1117c54f5b740e7a5 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 11:10:15 -0500 Subject: [PATCH 27/39] Tests working --- .../OVM/execution/OVM_ExecutionManager.gas-spec.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index ce7b255ee..6a62a09be 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -8,8 +8,8 @@ import { Contract, ContractFactory, Signer } from 'ethers' import { smockit, MockContract, - ModifiableContract, - smoddit + // ModifiableContract, + // smoddit } from '@eth-optimism/smock' /* Internal Imports */ @@ -125,7 +125,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { let OVM_SafetyCache: Contract let MOCK__OVM_DeployerWhitelist: MockContract - let MODDABLE__STATE_MANAGER: ModifiableContract + let MODDABLE__STATE_MANAGER: Contract let AddressManager: Contract let gasMeasurement: GasMeasurement let OVM_ExecutionManager: Contract @@ -177,7 +177,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { // Setup the State Manger and modify it to allow execution to proceed MODDABLE__STATE_MANAGER = await ( - await smoddit('OVM_StateManager') + await ethers.getContractFactory('OVM_StateManager') ).deploy( await wallet.getAddress() ) @@ -201,8 +201,6 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { await ethers.getContractFactory('Helper_SimpleOvmDeployer') ).deploy() DUMMY_TRANSACTION.entrypoint = Helper_SimpleDeployer.address - console.log("Helper_SimpleDeployer.address:" , Helper_SimpleDeployer.address); - await MODDABLE__STATE_MANAGER.putAccount( Helper_SimpleDeployer.address, From f51c0d68391b1f45e465936ad0040ec9e4402697 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 14:56:46 -0500 Subject: [PATCH 28/39] Save working tests with variable bytecode deployment --- .../test-helpers/Helper_SimpleOvmDeployer.sol | 19 ++++++++-- .../OVM_ExecutionManager.gas-spec.ts | 37 ++++++++++++------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol index bb58453f3..208c707e3 100644 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -4,13 +4,26 @@ import { Lib_SafeExecutionManagerWrapper } from "../optimistic-ethereum/librarie pragma solidity >0.5.0 <0.8.0; +import "hardhat/console.sol"; + contract Helper_SimpleOvmDeployer { - fallback() + // A fallback function that allows us to choose between deploying two different initCodes + function deploy(uint256 selection) external { - // the resulting deployed bytecode is 0x00 - bytes memory initCode = hex'600D380380600D6000396000f300'; + // uint256 selection = abi.decode(msg.data, (uint256)); + console.log('selection', selection); + bytes memory initCode; + if(selection == 0) { + // the resulting deployed bytecode is 0x00 + // do concat to be clear + initCode = hex'600D380380600D6000396000f300'; + } else if(selection == 1){ + initCode = hex'600D380380600D6000396000f36020'; + } + address addr = Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), initCode); + console.log("deployed address %s", addr); } } diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 6a62a09be..09951a4a0 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -37,16 +37,6 @@ const QUEUE_ORIGIN = { L1TOL2_QUEUE: 1, } -const DUMMY_TRANSACTION = { - timestamp: 111111111111, - blockNumber: 20, - l1QueueOrigin: QUEUE_ORIGIN.SEQUENCER_QUEUE, - l1TxOrigin: NON_ZERO_ADDRESS, - entrypoint: NON_ZERO_ADDRESS, // update this below - gasLimit: 10_000_000, - data: 0, -} - describe.only('OVM_ExecutionManager Benchmarks', () => { describe('em.run() benchmark: executing a minimal contract', async () => { let wallet: Signer @@ -56,12 +46,23 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { let AddressManager: Contract let targetContractAddress: string let gasMeasurement: GasMeasurement + let DUMMY_TRANSACTION; before(async () => { ;[wallet] = await ethers.getSigners() Factory__OVM_ExecutionManager = await ethers.getContractFactory( 'OVM_ExecutionManager' ) + DUMMY_TRANSACTION = { + timestamp: 111111111111, + blockNumber: 20, + l1QueueOrigin: QUEUE_ORIGIN.SEQUENCER_QUEUE, + l1TxOrigin: NON_ZERO_ADDRESS, + entrypoint: NON_ZERO_ADDRESS, // update this below + gasLimit: 10_000_000, + data: 0, + } + // Deploy a simple contract that just returns successfully with no data targetContractAddress = await deployContractCode( '60206001f3', @@ -129,6 +130,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { let AddressManager: Contract let gasMeasurement: GasMeasurement let OVM_ExecutionManager: Contract + let DUMMY_TRANSACTION before(async () => { ;[wallet] = await ethers.getSigners() @@ -170,7 +172,8 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { DUMMY_GASMETERCONFIG, DUMMY_GLOBALCONTEXT ) - + + // Deploy GasMeasurement utility gasMeasurement = new GasMeasurement() await gasMeasurement.init(wallet) @@ -200,8 +203,15 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { Helper_SimpleDeployer = await ( await ethers.getContractFactory('Helper_SimpleOvmDeployer') ).deploy() - DUMMY_TRANSACTION.entrypoint = Helper_SimpleDeployer.address - + DUMMY_TRANSACTION = { + timestamp: 111111111111, + blockNumber: 20, + l1QueueOrigin: QUEUE_ORIGIN.SEQUENCER_QUEUE, + l1TxOrigin: NON_ZERO_ADDRESS, + entrypoint: Helper_SimpleDeployer.address, + gasLimit: 10_000_000, + data: Helper_SimpleDeployer.interface.encodeFunctionData('deploy(uint256)', [0]) + } await MODDABLE__STATE_MANAGER.putAccount( Helper_SimpleDeployer.address, { @@ -220,7 +230,6 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { await MODDABLE__STATE_MANAGER.putEmptyAccount( "0xf7a70a9ed665630eaaf9f7b40b71f01cbf65f73f" ) - const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address) await tx.wait() const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed From 0a6a1f08d07b3e65b5632513b9679ab52fc0ea93 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 15:07:46 -0500 Subject: [PATCH 29/39] remove smoddit --- .../OVM/execution/OVM_StateManager.sol | 738 ------------------ .../test-helpers/Helper_SimpleOvmDeployer.sol | 29 - .../OVM_ExecutionManager.gas-spec.ts | 20 +- 3 files changed, 9 insertions(+), 778 deletions(-) delete mode 100644 contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol delete mode 100644 contracts/test-helpers/Helper_SimpleOvmDeployer.sol diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol deleted file mode 100644 index 2d8a95bc1..000000000 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol +++ /dev/null @@ -1,738 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >0.5.0 <0.8.0; -pragma experimental ABIEncoderV2; - -/* Library Imports */ -import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; - -/* Interface Imports */ -import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol"; - -/** - * @title OVM_StateManager - * @dev The State Manager contract holds all storage values for contracts in the OVM. It can only be written to by the - * the Execution Manager and State Transitioner. It runs on L1 during the setup and execution of a fraud proof. - * The same logic runs on L2, but has been implemented as a precompile in the L2 go-ethereum client - * (see https://github.com/ethereum-optimism/go-ethereum/blob/master/core/vm/ovm_state_manager.go). - * - * Compiler used: solc - * Runtime target: EVM - */ -contract OVM_StateManager is iOVM_StateManager { - - /************* - * Constants * - *************/ - - bytes32 constant internal EMPTY_ACCOUNT_STORAGE_ROOT = 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421; - bytes32 constant internal EMPTY_ACCOUNT_CODE_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - bytes32 constant internal STORAGE_XOR_VALUE = 0xFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEF; - - - /************* - * Variables * - *************/ - - address override public owner; - address override public ovmExecutionManager; - mapping (address => Lib_OVMCodec.Account) internal accounts; - mapping (address => mapping (bytes32 => bytes32)) internal contractStorage; - mapping (address => mapping (bytes32 => bool)) internal verifiedContractStorage; - mapping (bytes32 => ItemState) internal itemStates; - uint256 internal totalUncommittedAccounts; - uint256 internal totalUncommittedContractStorage; - - - /*************** - * Constructor * - ***************/ - - /** - * @param _owner Address of the owner of this contract. - */ - constructor( - address _owner - ) - { - owner = _owner; - } - - - /********************** - * Function Modifiers * - **********************/ - - /** - * Simple authentication, this contract should only be accessible to the owner (which is expected to be the State Transitioner during `PRE_EXECUTION` - * or the OVM_ExecutionManager during transaction execution. - */ - modifier authenticated() { - // owner is the State Transitioner - require( - msg.sender == owner || msg.sender == ovmExecutionManager, - "Function can only be called by authenticated addresses" - ); - _; - } - - /******************** - * Public Functions * - ********************/ - - /** - * Checks whether a given address is allowed to modify this contract. - * @param _address Address to check. - * @return Whether or not the address can modify this contract. - */ - function isAuthenticated( - address _address - ) - override - public - view - returns ( - bool - ) - { - return (_address == owner || _address == ovmExecutionManager); - } - - /** - * Sets the address of the OVM_ExecutionManager. - * @param _ovmExecutionManager Address of the OVM_ExecutionManager. - */ - function setExecutionManager( - address _ovmExecutionManager - ) - override - public - authenticated - { - ovmExecutionManager = _ovmExecutionManager; - } - - /** - * Inserts an account into the state. - * @param _address Address of the account to insert. - * @param _account Account to insert for the given address. - */ - function putAccount( - address _address, - Lib_OVMCodec.Account memory _account - ) - override - public - authenticated - { - accounts[_address] = _account; - } - - /** - * Marks an account as empty. - * @param _address Address of the account to mark. - */ - function putEmptyAccount( - address _address - ) - override - public - authenticated - { - Lib_OVMCodec.Account storage account = accounts[_address]; - account.storageRoot = EMPTY_ACCOUNT_STORAGE_ROOT; - account.codeHash = EMPTY_ACCOUNT_CODE_HASH; - } - - /** - * Retrieves an account from the state. - * @param _address Address of the account to retrieve. - * @return Account for the given address. - */ - function getAccount( - address _address - ) - override - public - view - returns ( - Lib_OVMCodec.Account memory - ) - { - return accounts[_address]; - } - - /** - * Checks whether the state has a given account. - * @param _address Address of the account to check. - * @return Whether or not the state has the account. - */ - function hasAccount( - address _address - ) - override - public - view - returns ( - bool - ) - { - return accounts[_address].codeHash != bytes32(0); - } - - /** - * Checks whether the state has a given known empty account. - * @param _address Address of the account to check. - * @return Whether or not the state has the empty account. - */ - function hasEmptyAccount( - address _address - ) - override - public - view - returns ( - bool - ) - { - return ( - accounts[_address].codeHash == EMPTY_ACCOUNT_CODE_HASH - && accounts[_address].nonce == 0 - ); - } - - /** - * Sets the nonce of an account. - * @param _address Address of the account to modify. - * @param _nonce New account nonce. - */ - function setAccountNonce( - address _address, - uint256 _nonce - ) - override - public - authenticated - { - accounts[_address].nonce = _nonce; - } - - /** - * Gets the nonce of an account. - * @param _address Address of the account to access. - * @return Nonce of the account. - */ - function getAccountNonce( - address _address - ) - override - public - view - returns ( - uint256 - ) - { - return accounts[_address].nonce; - } - - /** - * Retrieves the Ethereum address of an account. - * @param _address Address of the account to access. - * @return Corresponding Ethereum address. - */ - function getAccountEthAddress( - address _address - ) - override - public - view - returns ( - address - ) - { - return accounts[_address].ethAddress; - } - - /** - * Retrieves the storage root of an account. - * @param _address Address of the account to access. - * @return Corresponding storage root. - */ - function getAccountStorageRoot( - address _address - ) - override - public - view - returns ( - bytes32 - ) - { - return accounts[_address].storageRoot; - } - - /** - * Initializes a pending account (during CREATE or CREATE2) with the default values. - * @param _address Address of the account to initialize. - */ - function initPendingAccount( - address _address - ) - override - public - authenticated - { - Lib_OVMCodec.Account storage account = accounts[_address]; - account.nonce = 1; - account.storageRoot = EMPTY_ACCOUNT_STORAGE_ROOT; - account.codeHash = EMPTY_ACCOUNT_CODE_HASH; - account.isFresh = true; - } - - /** - * Finalizes the creation of a pending account (during CREATE or CREATE2). - * @param _address Address of the account to finalize. - * @param _ethAddress Address of the account's associated contract on Ethereum. - * @param _codeHash Hash of the account's code. - */ - function commitPendingAccount( - address _address, - address _ethAddress, - bytes32 _codeHash - ) - override - public - authenticated - { - Lib_OVMCodec.Account storage account = accounts[_address]; - account.ethAddress = _ethAddress; - account.codeHash = _codeHash; - } - - /** - * Checks whether an account has already been retrieved, and marks it as retrieved if not. - * @param _address Address of the account to check. - * @return Whether or not the account was already loaded. - */ - function testAndSetAccountLoaded( - address _address - ) - override - public - authenticated - returns ( - bool - ) - { - return _testAndSetItemState( - _getItemHash(_address), - ItemState.ITEM_LOADED - ); - } - - /** - * Checks whether an account has already been modified, and marks it as modified if not. - * @param _address Address of the account to check. - * @return Whether or not the account was already modified. - */ - function testAndSetAccountChanged( - address _address - ) - override - public - authenticated - returns ( - bool - ) - { - return _testAndSetItemState( - _getItemHash(_address), - ItemState.ITEM_CHANGED - ); - } - - /** - * Attempts to mark an account as committed. - * @param _address Address of the account to commit. - * @return Whether or not the account was committed. - */ - function commitAccount( - address _address - ) - override - public - authenticated - returns ( - bool - ) - { - bytes32 item = _getItemHash(_address); - if (itemStates[item] != ItemState.ITEM_CHANGED) { - return false; - } - - itemStates[item] = ItemState.ITEM_COMMITTED; - totalUncommittedAccounts -= 1; - - return true; - } - - /** - * Increments the total number of uncommitted accounts. - */ - function incrementTotalUncommittedAccounts() - override - public - authenticated - { - totalUncommittedAccounts += 1; - } - - /** - * Gets the total number of uncommitted accounts. - * @return Total uncommitted accounts. - */ - function getTotalUncommittedAccounts() - override - public - view - returns ( - uint256 - ) - { - return totalUncommittedAccounts; - } - - /** - * Checks whether a given account was changed during execution. - * @param _address Address to check. - * @return Whether or not the account was changed. - */ - function wasAccountChanged( - address _address - ) - override - public - view - returns ( - bool - ) - { - bytes32 item = _getItemHash(_address); - return itemStates[item] >= ItemState.ITEM_CHANGED; - } - - /** - * Checks whether a given account was committed after execution. - * @param _address Address to check. - * @return Whether or not the account was committed. - */ - function wasAccountCommitted( - address _address - ) - override - public - view - returns ( - bool - ) - { - bytes32 item = _getItemHash(_address); - return itemStates[item] >= ItemState.ITEM_COMMITTED; - } - - - /************************************ - * Public Functions: Storage Access * - ************************************/ - - /** - * Changes a contract storage slot value. - * @param _contract Address of the contract to modify. - * @param _key 32 byte storage slot key. - * @param _value 32 byte storage slot value. - */ - function putContractStorage( - address _contract, - bytes32 _key, - bytes32 _value - ) - override - public - authenticated - { - // A hilarious optimization. `SSTORE`ing a value of `bytes32(0)` is common enough that it's - // worth populating this with a non-zero value in advance (during the fraud proof - // initialization phase) to cut the execution-time cost down to 5000 gas. - contractStorage[_contract][_key] = _value ^ STORAGE_XOR_VALUE; - - // Only used when initially populating the contract storage. OVM_ExecutionManager will - // perform a `hasContractStorage` INVALID_STATE_ACCESS check before putting any contract - // storage because writing to zero when the actual value is nonzero causes a gas - // discrepancy. Could be moved into a new `putVerifiedContractStorage` function, or - // something along those lines. - if (verifiedContractStorage[_contract][_key] == false) { - verifiedContractStorage[_contract][_key] = true; - } - } - - /** - * Retrieves a contract storage slot value. - * @param _contract Address of the contract to access. - * @param _key 32 byte storage slot key. - * @return 32 byte storage slot value. - */ - function getContractStorage( - address _contract, - bytes32 _key - ) - override - public - view - returns ( - bytes32 - ) - { - // Storage XOR system doesn't work for newly created contracts that haven't set this - // storage slot value yet. - if ( - verifiedContractStorage[_contract][_key] == false - && accounts[_contract].isFresh - ) { - return bytes32(0); - } - - // See `putContractStorage` for more information about the XOR here. - return contractStorage[_contract][_key] ^ STORAGE_XOR_VALUE; - } - - /** - * Checks whether a contract storage slot exists in the state. - * @param _contract Address of the contract to access. - * @param _key 32 byte storage slot key. - * @return Whether or not the key was set in the state. - */ - function hasContractStorage( - address _contract, - bytes32 _key - ) - override - public - view - returns ( - bool - ) - { - return verifiedContractStorage[_contract][_key] || accounts[_contract].isFresh; - } - - /** - * Checks whether a storage slot has already been retrieved, and marks it as retrieved if not. - * @param _contract Address of the contract to check. - * @param _key 32 byte storage slot key. - * @return Whether or not the slot was already loaded. - */ - function testAndSetContractStorageLoaded( - address _contract, - bytes32 _key - ) - override - public - authenticated - returns ( - bool - ) - { - return _testAndSetItemState( - _getItemHash(_contract, _key), - ItemState.ITEM_LOADED - ); - } - - /** - * Checks whether a storage slot has already been modified, and marks it as modified if not. - * @param _contract Address of the contract to check. - * @param _key 32 byte storage slot key. - * @return Whether or not the slot was already modified. - */ - function testAndSetContractStorageChanged( - address _contract, - bytes32 _key - ) - override - public - authenticated - returns ( - bool - ) - { - return _testAndSetItemState( - _getItemHash(_contract, _key), - ItemState.ITEM_CHANGED - ); - } - - /** - * Attempts to mark a storage slot as committed. - * @param _contract Address of the account to commit. - * @param _key 32 byte slot key to commit. - * @return Whether or not the slot was committed. - */ - function commitContractStorage( - address _contract, - bytes32 _key - ) - override - public - authenticated - returns ( - bool - ) - { - bytes32 item = _getItemHash(_contract, _key); - if (itemStates[item] != ItemState.ITEM_CHANGED) { - return false; - } - - itemStates[item] = ItemState.ITEM_COMMITTED; - totalUncommittedContractStorage -= 1; - - return true; - } - - /** - * Increments the total number of uncommitted storage slots. - */ - function incrementTotalUncommittedContractStorage() - override - public - authenticated - { - totalUncommittedContractStorage += 1; - } - - /** - * Gets the total number of uncommitted storage slots. - * @return Total uncommitted storage slots. - */ - function getTotalUncommittedContractStorage() - override - public - view - returns ( - uint256 - ) - { - return totalUncommittedContractStorage; - } - - /** - * Checks whether a given storage slot was changed during execution. - * @param _contract Address to check. - * @param _key Key of the storage slot to check. - * @return Whether or not the storage slot was changed. - */ - function wasContractStorageChanged( - address _contract, - bytes32 _key - ) - override - public - view - returns ( - bool - ) - { - bytes32 item = _getItemHash(_contract, _key); - return itemStates[item] >= ItemState.ITEM_CHANGED; - } - - /** - * Checks whether a given storage slot was committed after execution. - * @param _contract Address to check. - * @param _key Key of the storage slot to check. - * @return Whether or not the storage slot was committed. - */ - function wasContractStorageCommitted( - address _contract, - bytes32 _key - ) - override - public - view - returns ( - bool - ) - { - bytes32 item = _getItemHash(_contract, _key); - return itemStates[item] >= ItemState.ITEM_COMMITTED; - } - - - /********************** - * Internal Functions * - **********************/ - - /** - * Generates a unique hash for an address. - * @param _address Address to generate a hash for. - * @return Unique hash for the given address. - */ - function _getItemHash( - address _address - ) - internal - pure - returns ( - bytes32 - ) - { - return keccak256(abi.encodePacked(_address)); - } - - /** - * Generates a unique hash for an address/key pair. - * @param _contract Address to generate a hash for. - * @param _key Key to generate a hash for. - * @return Unique hash for the given pair. - */ - function _getItemHash( - address _contract, - bytes32 _key - ) - internal - pure - returns ( - bytes32 - ) - { - return keccak256(abi.encodePacked( - _contract, - _key - )); - } - - /** - * Checks whether an item is in a particular state (ITEM_LOADED or ITEM_CHANGED) and sets the - * item to the provided state if not. - * @param _item 32 byte item ID to check. - * @param _minItemState Minimum state that must be satisfied by the item. - * @return Whether or not the item was already in the state. - */ - function _testAndSetItemState( - bytes32 _item, - ItemState _minItemState - ) - internal - returns ( - bool - ) - { - bool wasItemState = itemStates[_item] >= _minItemState; - - if (wasItemState == false) { - itemStates[_item] = _minItemState; - } - - return wasItemState; - } -} diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol deleted file mode 100644 index 208c707e3..000000000 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -// SPDX-License-Identifier: MIT -import { Lib_SafeExecutionManagerWrapper } from "../optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol"; - -pragma solidity >0.5.0 <0.8.0; - -import "hardhat/console.sol"; - -contract Helper_SimpleOvmDeployer { - - // A fallback function that allows us to choose between deploying two different initCodes - function deploy(uint256 selection) - external - { - // uint256 selection = abi.decode(msg.data, (uint256)); - console.log('selection', selection); - bytes memory initCode; - if(selection == 0) { - // the resulting deployed bytecode is 0x00 - // do concat to be clear - initCode = hex'600D380380600D6000396000f300'; - } else if(selection == 1){ - initCode = hex'600D380380600D6000396000f36020'; - } - - address addr = Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), initCode); - console.log("deployed address %s", addr); - } -} diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 09951a4a0..864c5a543 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -8,8 +8,6 @@ import { Contract, ContractFactory, Signer } from 'ethers' import { smockit, MockContract, - // ModifiableContract, - // smoddit } from '@eth-optimism/smock' /* Internal Imports */ @@ -126,7 +124,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { let OVM_SafetyCache: Contract let MOCK__OVM_DeployerWhitelist: MockContract - let MODDABLE__STATE_MANAGER: Contract + let OVM_StateManager: Contract let AddressManager: Contract let gasMeasurement: GasMeasurement let OVM_ExecutionManager: Contract @@ -179,14 +177,14 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { await gasMeasurement.init(wallet) // Setup the State Manger and modify it to allow execution to proceed - MODDABLE__STATE_MANAGER = await ( + OVM_StateManager = await ( await ethers.getContractFactory('OVM_StateManager') ).deploy( await wallet.getAddress() ) // Setup the SM to satisfy all the checks executed during EM.run() - await MODDABLE__STATE_MANAGER.putAccount( + await OVM_StateManager.putAccount( "0x4200000000000000000000000000000000000002", { nonce: BigNumber.from(123), @@ -196,7 +194,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { ethAddress: MOCK__OVM_DeployerWhitelist.address, }, ); - await MODDABLE__STATE_MANAGER.setExecutionManager(OVM_ExecutionManager.address) + await OVM_StateManager.setExecutionManager(OVM_ExecutionManager.address) // Deploy a simple OVM-safe contract that just deploys another contract @@ -212,7 +210,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { gasLimit: 10_000_000, data: Helper_SimpleDeployer.interface.encodeFunctionData('deploy(uint256)', [0]) } - await MODDABLE__STATE_MANAGER.putAccount( + await OVM_StateManager.putAccount( Helper_SimpleDeployer.address, { nonce: BigNumber.from(123), @@ -227,10 +225,10 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { it('Gas Benchmark: un-cached contract deployment', async () => { // Set destination for first contract deployment - await MODDABLE__STATE_MANAGER.putEmptyAccount( + await OVM_StateManager.putEmptyAccount( "0xf7a70a9ed665630eaaf9f7b40b71f01cbf65f73f" ) - const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address) + const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, OVM_StateManager.address) await tx.wait() const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) @@ -245,12 +243,12 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { it('Gas Benchmark: deploying a cached contract', async () => { // Set destination for second contract deployment - await MODDABLE__STATE_MANAGER.putEmptyAccount( + await OVM_StateManager.putEmptyAccount( "0xd236d314fd67606dddb3885f1330cf9bd3c8dbea" ) // run the exact same flow as the previous. This time the Safety Cache should recognize the string. - const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, MODDABLE__STATE_MANAGER.address) + const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, OVM_StateManager.address) await tx.wait() const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) From a768a057b2445262c6edfbf651ff6cac76a79e93 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 15:09:14 -0500 Subject: [PATCH 30/39] Add Simple Deployer --- .../test-helpers/Helper_SimpleOvmDeployer.sol | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 contracts/test-helpers/Helper_SimpleOvmDeployer.sol diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol new file mode 100644 index 000000000..45f7966b0 --- /dev/null +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: UNLICENSED +// SPDX-License-Identifier: MIT +import { Lib_SafeExecutionManagerWrapper } from "../optimistic-ethereum/libraries/wrappers/Lib_SafeExecutionManagerWrapper.sol"; + +pragma solidity >0.5.0 <0.8.0; + +import "hardhat/console.sol"; + +contract Helper_SimpleOvmDeployer { + + // A fallback function that allows us to choose between deploying two different initCodes + function deploy(uint256 selection) + external + { + bytes memory initCode; + if(selection == 0) { + // the resulting deployed bytecode is 0x00 + // do concat to be clear + initCode = hex'600D380380600D6000396000f300'; + } else if(selection == 1){ + initCode = hex'600D380380600D6000396000f36020'; + } + + address addr = Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), initCode); + console.log("deployed address %s", addr); + } +} From 23df0bde0e70771b8c5696677c8f8795bc6f83ee Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 15:27:57 -0500 Subject: [PATCH 31/39] working deployment of large bytecode --- .../OVM/execution/OVM_ExecutionManager.sol | 3 ++ .../test-helpers/Helper_SimpleOvmDeployer.sol | 9 +++- .../OVM_ExecutionManager.gas-spec.ts | 42 ++++++++++++++++++- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index 42c0c858d..c5b2994c0 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -3,6 +3,8 @@ pragma solidity >0.5.0 <0.8.0; pragma experimental ABIEncoderV2; +import "hardhat/console.sol"; + /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; @@ -806,6 +808,7 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // some existing contract. On L1, users will prove that no contract exists at the address // and the OVM_FraudVerifier will populate the code hash of this address with a special // value that represents "known to be an empty account." + console.log(_address); if (_hasEmptyAccount(_address) == false) { _revertWithFlag(RevertFlag.CREATE_COLLISION); } diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol index 45f7966b0..2578021b5 100644 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -8,17 +8,22 @@ import "hardhat/console.sol"; contract Helper_SimpleOvmDeployer { + bytes constant largeBytecode = hex"608060405234801561001957600080610016614e7b565b50505b506004361061031d5760003560e01c8063654a60ac116101b0578063935f4abd116100f7578063c2c8a676116100a0578063ce8480ea1161007a578063ce8480ea14610e1a578063de02795e14610e40578063fdadbc7e14610e665761031d565b8063c2c8a67614610c70578063c8e5bbd514610d04578063c8e6f39514610df45761031d565b8063b199c764116100d1578063b199c76414610aeb578063b295ad3414610b33578063bfa005ce14610b6f5761031d565b8063935f4abd14610a79578063ac82f60814610a9f578063af3aea8614610ac55761031d565b80637adbf973116101595780638295016a116101335780638295016a14610a13578063899ffef414610a695780638da5cb5b14610a715761031d565b80637adbf973146109a95780637dc0d1d0146109e55780637f6e9d15146109ed5761031d565b8063741853601161018a578063741853601461097357806379ba50971461097b5780637a018a1e146109835761031d565b8063654a60ac146108c25780637103353e146108f4578063728dec291461091a5761031d565b80632af64bd3116102745780633f0e084f1161021d5780634c36b837116101f75780634c36b8371461088c5780634f72def61461089457806353a47bb7146108ba5761031d565b80633f0e084f146107e65780634308a94f1461082857806345938849146108665761031d565b80632ea913d41161024e5780632ea913d4146107745780633375fcd11461079a57806338aa1b99146107c05761031d565b80632af64bd3146106815780632bed9e0c146106895780632d7371e1146106af5761031d565b80630ee4951b116102d65780632528f0fe116102b05780632528f0fe146105e1578063266da16b146106075780632678df96146106455761031d565b80630ee4951b14610551578063109e46a21461056b5780631627540c146105a35761031d565b806305a046e51161030757806305a046e5146103965780630a7d36d11461047d5780630c71cd23146105115761031d565b80629919c01461032b57806304f3bcec14610365575b600080610328614e7b565b50505b6103516004803603602081101561034a57600080610347614e7b565b50505b5035610e92565b604051901515815260200160405180910390f35b61036d610ead565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61042a600480360360208110156103b5576000806103b2614e7b565b50505b8101906020810181356401000000008111156103d9576000806103d6614e7b565b50505b8201836020820111156103f4576000806103f1614e7b565b50505b8035906020019184602083028401116401000000008311171561041f5760008061041c614e7b565b50505b509092509050610ed9565b60405160208082528190810183818151815260200191508051906020019060200280838360005b83811015610469578082015183820152602001610451565b505050509050019250505060405180910390f35b6103516004803603602081101561049c57600080610499614e7b565b50505b8101906020810181356401000000008111156104c0576000806104bd614e7b565b50505b8201836020820111156104db576000806104d8614e7b565b50505b8035906020019184602083028401116401000000008311171561050657600080610503614e7b565b50505b509092509050610f58565b610537600480360360208110156105305760008061052d614e7b565b50505b503561100b565b604051918252151560208201526040908101905180910390f35b6105596110d4565b60405190815260200160405180910390f35b6105596004803603608081101561058a57600080610587614e7b565b50505b50803590602081013590604081013590606001356110e4565b6105df600480360360208110156105c2576000806105bf614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff16611127565b005b61035160048036036020811015610600576000806105fd614e7b565b50505b50356111c8565b610559600480360360a081101561062657600080610623614e7b565b50505b50803590602081013590604081013590606081013590608001356111e8565b61042a6004803603602081101561066457600080610661614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff16611255565b61035161136e565b6105df600480360360208110156106a8576000806106a5614e7b565b50505b5035611563565b6106db600480360360408110156106ce576000806106cb614e7b565b50505b50803590602001356116d1565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561071f578082015183820152602001610707565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561075e578082015183820152602001610746565b5050505090500194505050505060405180910390f35b6105596004803603602081101561079357600080610790614e7b565b50505b50356117c2565b610351600480360360208110156107b9576000806107b6614e7b565b50505b50356117ed565b610351600480360360208110156107df576000806107dc614e7b565b50505b50356118eb565b6105df6004803603604081101561080557600080610802614e7b565b50505b508035906020013573ffffffffffffffffffffffffffffffffffffffff166118f9565b61084e6004803603602081101561084757600080610844614e7b565b50505b5035611c94565b60405191825260208201526040908101905180910390f35b6105df6004803603602081101561088557600080610882614e7b565b50505b5035611ce1565b61036d611e78565b610559600480360360208110156108b3576000806108b0614e7b565b50505b5035611e82565b61036d611e8e565b610559600480360360608110156108e1576000806108de614e7b565b50505b5080359060208101359060400135611e9a565b61036d6004803603602081101561091357600080610910614e7b565b50505b5035611eb2565b6109406004803603602081101561093957600080610936614e7b565b50505b5035611ecc565b604051948552602085019390935260408085019290925215156060840152901515608083015260a0909101905180910390f35b6105df611f37565b6105df6121ab565b610559600480360360208110156109a25760008061099f614e7b565b50505b50356123b8565b6105df600480360360208110156109c8576000806109c5614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff166123c3565b61036d61248e565b61055960048036036020811015610a0c57600080610a09614e7b565b50505b503561249a565b610a4560048036036060811015610a3257600080610a2f614e7b565b50505b50803590602081013590604001356124b2565b60405180848152602001838152602001828152602001935050505060405180910390f35b61042a6124d2565b61036d61255a565b61055960048036036020811015610a9857600080610a95614e7b565b50505b5035612565565b61055960048036036020811015610abe57600080610abb614e7b565b50505b503561257d565b61035160048036036020811015610ae457600080610ae1614e7b565b50505b50356125ac565b6105df600480360360c0811015610b0a57600080610b07614e7b565b50505b50803590602081013590604081013590606081013590608081013515159060a0013515156125b7565b610b5960048036036020811015610b5257600080610b4f614e7b565b50505b5035612aaf565b60405160ff909116815260200160405180910390f35b61035160048036036060811015610b8e57600080610b8b614e7b565b50505b810190602081018135640100000000811115610bb257600080610baf614e7b565b50505b820183602082011115610bcd57600080610bca614e7b565b50505b80359060200191846020830284011164010000000083111715610bf857600080610bf5614e7b565b50505b919390929091602081019035640100000000811115610c1f57600080610c1c614e7b565b50505b820183602082011115610c3a57600080610c37614e7b565b50505b80359060200191846020830284011164010000000083111715610c6557600080610c62614e7b565b50505b919350915035612ad6565b61042a60048036036020811015610c8f57600080610c8c614e7b565b50505b810190602081018135640100000000811115610cb357600080610cb0614e7b565b50505b820183602082011115610cce57600080610ccb614e7b565b50505b80359060200191846020830284011164010000000083111715610cf957600080610cf6614e7b565b50505b509092509050612b5d565b610d9860048036036020811015610d2357600080610d20614e7b565b50505b810190602081018135640100000000811115610d4757600080610d44614e7b565b50505b820183602082011115610d6257600080610d5f614e7b565b50505b80359060200191846020830284011164010000000083111715610d8d57600080610d8a614e7b565b50505b509092509050612bd2565b604051811515602082015260408082528190810184818151815260200191508051906020019060200280838360005b83811015610ddf578082015183820152602001610dc7565b50505050905001935050505060405180910390f35b6105df60048036036020811015610e1357600080610e10614e7b565b50505b5035612d40565b61055960048036036020811015610e3957600080610e36614e7b565b50505b5035612ea3565b6105df60048036036020811015610e5f57600080610e5c614e7b565b50505b5035612eae565b61084e60048036036040811015610e8557600080610e82614e7b565b50505b508035906020013561315a565b6000610ea582610ea0613172565b613293565b90505b919050565b60006002610eb9614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60608082604051908082528060200260200182016040528015610f06578160200160208202803883390190505b50905060005b83811015610f4e57610f2f858583818110610f2357fe5b905060200201356132de565b828281518110610f3b57fe5b6020908102919091010152600101610f0c565b5090505b92915050565b600080610f63613172565b90506060610fa38585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132fa92505050565b905060005b84811015610fff57818181518110610fbc57fe5b602002602001015180610fe65750610fe6868683818110610fd957fe5b9050602002013584613293565b15610ff75760019350505050610f52565b600101610fa8565b50600095945050505050565b600080611016614f41565b61101f846135e4565b9050837f735553440000000000000000000000000000000000000000000000000000000014156110755780517affffffffffffffffffffffffffffffffffffffffffffffffffffff169250600091506110cf9050565b8051611093611082613172565b836020015164ffffffffff16613985565b806110aa57506110aa856110a56139a8565b613a5e565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff90911693509150505b915091565b60006110de613172565b90505b90565b600083815b6110f68783600101613be4565b915050801580611107575083850181115b156111145750905061111f565b6001909101906110e9565b949350505050565b61112f613f0a565b806001808061113c614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790611178614f58565b5050507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce228160405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b60006111d682610ea0613172565b80610ea55750610ea5826110a56139a8565b6000838614156111f957508361124c565b60006112058785613be4565b50905060006112148685613be4565b509050806112275760009250505061124c565b6112478161123b898563ffffffff613fab16565b9063ffffffff613fc016565b925050505b95945050505050565b60606000600880611264614ee6565b905060405190808252806020026020018201604052801561128f578160200160208202803883390190505b50915060005b6008806112a0614ee6565b9050811015611367576000600882816112b7614ee6565b81106112bf57fe5b906000526020600020016112d1614ee6565b6000818152600660205290915073ffffffffffffffffffffffffffffffffffffffff86169060409020600090611305614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561135e578084848060010195508151811061135157fe5b6020026020010181815250505b50600101611295565b5050919050565b6000606061137a6124d2565b905060005b815181101561155a57600082828151811061139657fe5b602002602001015160008181526003602052909150604090206000906113ba614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416600060026113e5614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166321f8a721836040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815260048101919091526024016020604051808303818680611468614fa6565b15801561147d5760008061147a614e7b565b50505b505a611487614ff2565b50505050501580156114a6573d6000803e3d60006114a3614e7b565b50505b505050506040513d60208110156114c5576000806114c2614e7b565b50505b81019080805173ffffffffffffffffffffffffffffffffffffffff169390931415925082915061154090505750600081815260036020526040812060009061150b614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b1561155157600093505050506110e1565b5060010161137f565b50600191505090565b61156b613f0a565b6000818152600660205260408120600090611584614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a9004169050806115ff5760405162461bcd60e51b815260206004820152601c60248201527f4e6f2061676772656761746f722065786973747320666f72206b6579000000006044820152606401604051809103906115fc614e7b565b50505b6000828152600660205260409020600181611618614ee6565b9073ffffffffffffffffffffffffffffffffffffffff0219169061163a614f58565b50506000828152600760205260409020600181611655614ee6565b9060ff02191690611664614f58565b50506000611673836008613fd5565b905080156116cc577fec70e890fc7db7de4059b114c9093a1f41283d18ffcfbcac45566feea4d4f777838360405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a15b505050565b606080826040519080825280602002602001820160405280156116fe578160200160208202803883390190505b5091508260405190808252806020026020018201604052801561172b578160200160208202803883390190505b5090506000611739856140f3565b905060005b848110156117b8576117508683613be4565b85838151811061175c57fe5b6020026020010185848151811061176f57fe5b6020908102919091010191909152528161178b57506117bb9050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019060010161173e565b50505b9250929050565b600a81816117ce614ee6565b81106117d657fe5b9060005260206000200190506117ea614ee6565b81565b60006117f76150dd565b600083815260096020526040902060405160a0810160405290818161181a614ee6565b81526020016001820161182b614ee6565b81526020016002820161183c614ee6565b815260200160006003830161184f614ee6565b60ff6101009290920a90041615158152602001600160038301611870614ee6565b60ff6101009290920a9004161515905250905080511580611892575080606001515b8061189e575080608001515b156118ad576000915050610ea8565b60006118b88461257d565b90506000811180156118dc57508160200151811015806118dc575081604001518111155b92505050610ea8565b50919050565b6000610ea5826110a56139a8565b611901613f0a565b80600073ffffffffffffffffffffffffffffffffffffffff821663668a0f026040518163ffffffff1660e01b81526004016020604051808303818680611945614fa6565b15801561195a57600080611957614e7b565b50505b505a611964614ff2565b5050505050158015611983573d6000803e3d6000611980614e7b565b50505b505050506040513d60208110156119a25760008061199f614e7b565b50505b81019080805193909310159250611a0b9150505760405162461bcd60e51b815260206004820152601b60248201527f476976656e2041676772656761746f7220697320696e76616c69640000000000604482015260640160405180910390611a08614e7b565b50505b60008173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b81526004016020604051808303818680611a4e614fa6565b158015611a6357600080611a60614e7b565b50505b505a611a6d614ff2565b5050505050158015611a8c573d6000803e3d6000611a89614e7b565b50505b505050506040513d6020811015611aab57600080611aa8614e7b565b50505b81019080805193505050601260ff831611159050611b035760405162461bcd60e51b815260040180806020018281038252603281526020018061541f6032913960400191505060405180910390611b00614e7b565b50505b6000848152600660205260408120600090611b1c614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611bb05783600880600181611b64614ee6565b018082611b6f614f58565b50506000928352917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830191506020902091929101611bac614f58565b5050505b60008481526006602052829060409020600181611bcb614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790611c07614f58565b50505060008481526007602052819060409020600181611c25614ee6565b8160ff021916908360ff16021790611c3b614f58565b5050507f0bcae573430f69c5361e5d76534d3f61d2d803958778680cd74be9dc6299bc63848360405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a150505050565b600080611c9f614f41565b611ca8846135e4565b9050805181602001517affffffffffffffffffffffffffffffffffffffffffffffffffffff909116935064ffffffffff16915050915091565b611ce9614202565b6000611cf48261257d565b11611d4e5760405162461bcd60e51b815260206004820152600c60248201527f52617465206973207a65726f0000000000000000000000000000000000000000604482015260640160405180910390611d4b614e7b565b50505b60008181526004602052604090206000828152600b60205260408120611d72614ee6565b8152602001908152602001600020600081600181611d8e614ee6565b907affffffffffffffffffffffffffffffffffffffffffffffffffffff02191690611db7614f58565b508290507b0100000000000000000000000000000000000000000000000000000081611de1614ee6565b9064ffffffffff02191690611df4614f58565b5050506000828152600b6020526040915020600081611e11614ee6565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019150611e3f614f58565b5050507fe69d655565c7ff1353d8eaeea62fb7904fa9696987431ec351be288c865f1ae18160405190815260200160405180910390a150565b60006110de6139a8565b600881816117ce614ee6565b60006001610eb9614ee6565b6000611ea78484846142a2565b509095945050505050565b600660205280600052604060002060009150610eb9614ee6565b6009602052806000526040600020905080611ee5614ee6565b9080600101611ef2614ee6565b9080600201611eff614ee6565b90600060038201611f0e614ee6565b906101000a900460ff169080600301600190611f28614ee6565b906101000a900460ff16905085565b6060611f416124d2565b905060005b81518110156121a7576000828281518110611f5d57fe5b602002602001015190506000806002611f74614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dacb2d0183846040517f5265736f6c766572206d697373696e67207461726765743a2000000000000000602082015260398101919091526059016040516020818303038152906040526040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561204357808201518382015260200161202b565b50505050905090810190601f1680156120705780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818680612089614fa6565b15801561209e5760008061209b614e7b565b50505b505a6120a8614ff2565b50505050501580156120c7573d6000803e3d60006120c4614e7b565b50505b505050506040513d60208110156120e6576000806120e3614e7b565b50505b810190808051600086815260036020529094508493506040925090502060018161210e614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179061214a614f58565b5050507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68828260405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a15050600101611f46565b5050565b600060016121b7614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a6121f361510a565b73ffffffffffffffffffffffffffffffffffffffff161461224e5760405162461bcd60e51b81526004018080602001828103825260358152602001806152b5603591396040019150506040518091039061224b614e7b565b50505b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c60008061227a614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660016000906122a4614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff9283168152911660208201526040908101905180910390a1600060016122fd614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a8161232a614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790612366614f58565b5050506000600160006101000a8161237c614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906116cc614f58565b6000610ea5826140f3565b6123cb613f0a565b8060056001816123d9614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790612415614f58565b5050507f3df77beb5db05fcdd70a30fc8adf3f83f9501b68579455adbd100b81809403946005600090612446614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b60006005610eb9614ee6565b600c60205280600052604060002090506117ea614ee6565b60008060006124c28686866142a2565b9250925092505b93509350939050565b6060806124dd6142f4565b90506060600160405190808252806020026020018201604052801561250c578160200160208202803883390190505b5090507f45786368616e67657200000000000000000000000000000000000000000000008160008151811061253d57fe5b6020026020010181815250506125538282614361565b9250505090565b600080610eb9614ee6565b600b60205280600052604060002090506117ea614ee6565b6000612588826135e4565b517affffffffffffffffffffffffffffffffffffffffffffffffffffff1692915050565b6000610ea58261441d565b6125bf613f0a565b6000831161261c5760405162461bcd60e51b815260206004820152601a60248201527f6c6f7765724c696d6974206d7573742062652061626f76652030000000000000604482015260640160405180910390612619614e7b565b50505b8484116126635760405162461bcd60e51b815260040180806020018281038252602781526020018061548a6027913960400191505060405180910390612660614e7b565b50505b61267485600263ffffffff6144ca16565b84106126ba5760405162461bcd60e51b815260040180806020018281038252602e8152602001806153f1602e9139604001915050604051809103906126b7614e7b565b50505b8483106127015760405162461bcd60e51b81526004018080602001828103825260278152602001806153ca60279139604001915050604051809103906126fe614e7b565b50505b81801561270b5750805b156127655760405162461bcd60e51b815260206004820152601c60248201527f43616e6e6f7420667265657a6520617420626f7468206c696d69747300000000604482015260640160405180910390612762614e7b565b50505b600086815260096020526040812090508061277e614ee6565b6127dd5786600a80600181612791614ee6565b01808261279c614f58565b50506000928352917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301915060209020919291016127d9614f58565b5050505b8580826127e8614f58565b505050848160010181906127fa614f58565b5050508381600201819061280c614f58565b50505082806128185750815b1561291957826003820160018161282d614ee6565b8160ff02191690831515021790612842614f58565b50839150506003820161010081612857614ee6565b8160ff0219169083151502179061286c614f58565b505050600061287a886140f3565b6000898152600c6020529091508190604090208190612897614f58565b5050507ff72828471e37526c68fd812a1fa6eeff993c3f81bd96c0242dc5b3e144145df088856128c757866128c9565b875b835a6128d361510a565b604051938452602084019290925260408084019190915273ffffffffffffffffffffffffffffffffffffffff90911660608301526080909101905180910390a150612989565b60006003820160018161292a614ee6565b8160ff0219169083151502179061293f614f58565b5060009150506003820161010081612955614ee6565b8160ff0219169083151502179061296a614f58565b5050506000878152600c602052604081208190612985614f58565b5050505b60006129948861257d565b90508015612a56576129a4614532565b73ffffffffffffffffffffffffffffffffffffffff1663ce09694089836040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526004810192909252602482015260440160006040518083038160008780612a12614fa6565b158015612a2757600080612a24614e7b565b50505b505a612a31615150565b505050505050158015612a51573d6000803e3d6000612a4e614e7b565b50505b505050505b7f37efb38e92b0f94698f6df0c9070e2f00946862a042ac09e34ae8c547684240a888888886040518085815260200184815260200183815260200182815260200194505050505060405180910390a15050505050505050565b600760205280600052604060002060009150612ac9614ee6565b906101000a900460ff1681565b6000612ae0614202565b612b53868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250889250879150819050602080820201604051908101604052809392919081815260200183836020028082843760009201919091525087925061455d915050565b9695505050505050565b60608082604051908082528060200260200182016040528015612b8a578160200160208202803883390190505b50905060005b83811015610f4e57612bb3858583818110612ba757fe5b9050602002013561257d565b828281518110612bbf57fe5b6020908102919091010152600101612b90565b6060600082604051908082528060200260200182016040528015612c00578160200160208202803883390190505b5091506000612c0d613172565b90506060612c4d8686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132fa92505050565b905060005b85811015612d3657612c62614f41565b612c7d888884818110612c7157fe5b905060200201356135e4565b905080517affffffffffffffffffffffffffffffffffffffffffffffffffffff16868381518110612caa57fe5b60200260200101818152505084158015612cf65750878783818110612ccb57fe5b905060200201357f735553440000000000000000000000000000000000000000000000000000000014155b15612d2d57828281518110612d0757fe5b602002602001015180612d2a5750612d2a84826020015164ffffffffff16613985565b94505b50600101612c52565b5050509250929050565b612d48613f0a565b6000818152600960205260408120612d5e614ee6565b11612db85760405162461bcd60e51b815260206004820152601860248201527f4e6f20696e766572746564207072696365206578697374730000000000000000604482015260640160405180910390612db5614e7b565b50505b600081815260096020526040902060008082612dd2614f58565b505060018201600090612de3614f58565b505060028201600090612df4614f58565b505060038201600181612e05614ee6565b9060ff02191690612e14614f58565b50506003820161010081612e26614ee6565b9060ff02191690612e35614f58565b505050506000612e4682600a613fd5565b905080156121a7577f37efb38e92b0f94698f6df0c9070e2f00946862a042ac09e34ae8c547684240a8260008060006040518085815260200184815260200183815260200182815260200194505050505060405180910390a15050565b6000610ea5826132de565b60008181526009602052604081209050600081612ec9614ee6565b11612f235760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f7420667265657a65206e6f6e2d696e766572736520726174650000604482015260640160405180910390612f20614e7b565b50505b600060038201612f31614ee6565b906101000a900460ff16158015612f5d5750600160038201612f51614ee6565b906101000a900460ff16155b612fb65760405162461bcd60e51b815260206004820152601a60248201527f546865207261746520697320616c72656164792066726f7a656e000000000000604482015260640160405180910390612fb3614e7b565b50505b6000612fc18361257d565b9050600081118015612ff3575081600101612fda614ee6565b81101580612ff3575081600201612fef614ee6565b8111155b156131015781600101613004614ee6565b811460038301600181613015614ee6565b8160ff0219169083151502179061302a614f58565b50505081600201613039614ee6565b8114600383016101008161304b614ee6565b8160ff02191690831515021790613060614f58565b505050600061306e846140f3565b6000858152600c602052909150819060409020819061308b614f58565b5050507ff72828471e37526c68fd812a1fa6eeff993c3f81bd96c0242dc5b3e144145df08483835a6130bb61510a565b604051938452602084019290925260408084019190915273ffffffffffffffffffffffffffffffffffffffff90911660608301526080909101905180910390a1506116cc565b60405162461bcd60e51b815260206004820152601260248201527f526174652077697468696e20626f756e64730000000000000000000000000000604482015260640160405180910390613153614e7b565b5050505050565b6000806131678484613be4565b915091509250929050565b600061317c6147f8565b73ffffffffffffffffffffffffffffffffffffffff166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f726174655374616c65506572696f6400000000000000000000000000000000006040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303818680613228614fa6565b15801561323d5760008061323a614e7b565b50505b505a613247614ff2565b5050505050158015613266573d6000803e3d6000613263614e7b565b50505b505050506040513d602081101561328557600080613282614e7b565b50505b810190808051935050505090565b6000827f735553440000000000000000000000000000000000000000000000000000000014156132c557506000610f52565b6132d7826132d2856132de565b613985565b9392505050565b60006132e9826135e4565b6020015164ffffffffff1692915050565b606060006133066139a8565b905073ffffffffffffffffffffffffffffffffffffffff8116156135b15760608351604051908082528060200260200182016040528015613351578160200160208202803883390190505b50905060005b84518110156133e7576006600086838151811061337057fe5b60200260200101518152602001908152602001600020600090613391614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff168282815181106133ba57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101613357565b508173ffffffffffffffffffffffffffffffffffffffff16637d723cac826040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b8381101561345457808201518382015260200161343c565b50505050905001925050506000604051808303818680613472614fa6565b15801561348757600080613484614e7b565b50505b505a613491614ff2565b50505050501580156134b0573d6000803e3d60006134ad614e7b565b50505b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526020811015613500576000806134fd614e7b565b50505b810190808051604051939291908464010000000082111561352957600080613526614e7b565b50505b90830190602082018581111561354757600080613544614e7b565b50505b825186602082028301116401000000008211171561356d5760008061356a614e7b565b50505b825250602001908051906020019060200280838360005b8381101561359c578082015183820152602001613584565b505050509050016040525050509250506118e5565b82516040519080825280602002602001820160405280156135dc578160200160208202803883390190505b509392505050565b6135ec614f41565b6000828152600660205260408120600090613605614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416905080156138775760606040516024016040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08183030181526040919091527ffeaf968c000000000000000000000000000000000000000000000000000000006020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909117905290506000606073ffffffffffffffffffffffffffffffffffffffff8416836040518082805190602001908083835b6020831061371957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016136dc565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855a613751614ff2565b50505050509150503d80600081146137a3576040513d603f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01681016040523d815291503d6000602084013e6137a8565b606091505b5091509150811561386f576000808060208401845160a08110156137d4576000806137d1614e7b565b50505b810190808051929190602001805192919060200180519291906020018051929190602001805150959850939650909450604093505050505180604001604052806138348b6138228d87614823565b8769ffffffffffffffffffff166148fb565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018264ffffffffff16815250975050505050505050610ea8565b5050506118e5565b6000838152600b6020526040812061388d614ee6565b9050613897614f41565b60008581526004602052604090206000838152602091909152604090206040516040808201905290816000826138cb614ee6565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff6101009290920a9004168152602001601b82613901614ee6565b64ffffffffff6101009290920a9004169052509050604051604080820190528061394a8784517affffffffffffffffffffffffffffffffffffffffffffffffffffff16866148fb565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff168152602001826020015164ffffffffff168152509350505050610ea8565b60005a613990615216565b6139a0838563ffffffff614a7816565b109392505050565b60006139b26147f8565b73ffffffffffffffffffffffffffffffffffffffff16639ee5955a7f53797374656d53657474696e67730000000000000000000000000000000000007f61676772656761746f725761726e696e67466c616773000000000000000000006040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303818680613228614fa6565b6000827f73555344000000000000000000000000000000000000000000000000000000001415613a9057506000610f52565b6000838152600660205260408120600090613aa9614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a9004169050801580613aeb575073ffffffffffffffffffffffffffffffffffffffff8316155b15613afa576000915050610f52565b8273ffffffffffffffffffffffffffffffffffffffff1663357e47fe826040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016020604051808303818680613b76614fa6565b158015613b8b57600080613b88614e7b565b50505b505a613b95614ff2565b5050505050158015613bb4573d6000803e3d6000613bb1614e7b565b50505b505050506040513d6020811015613bd357600080613bd0614e7b565b50505b810190808051979650505050505050565b60008281526006602052808060408120600090613bff614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a90041690508015613e395760608460405160248101919091526044016040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08183030181526040919091527f9a6fc8f5000000000000000000000000000000000000000000000000000000006020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909117905290506000606073ffffffffffffffffffffffffffffffffffffffff8416836040518082805190602001908083835b60208310613d1c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613cdf565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855a613d54614ff2565b50505050509150503d8060008114613da6576040513d603f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01681016040523d815291503d6000602084013e613dab565b606091505b50915091508115613e315760008060208301835160a0811015613dd657600080613dd3614e7b565b50505b8101908080519291906020018051929190602001805192919060200180519291906020018051906020019092919050505050935050925050613e228a613e1c8c85614823565b8b6148fb565b975095506117bb945050505050565b505050613f02565b613e41614f41565b6000868152600460205260409020600086815260209190915260409020604051604080820190529081600082613e75614ee6565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff6101009290920a9004168152602001601b82613eab614ee6565b64ffffffffff6101009290920a9004169052509050613ee98682517affffffffffffffffffffffffffffffffffffffffffffffffffffff16876148fb565b816020015190945064ffffffffff1692506117bb915050565b509250929050565b600080613f15614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a613f5161510a565b73ffffffffffffffffffffffffffffffffffffffff1614613fa95760405162461bcd60e51b815260040180806020018281038252602f815260200180615342602f9139604001915050604051809103906121a7614e7b565b565b60006132d78383670de0b6b3a7640000614ad7565b60006132d78383670de0b6b3a7640000614b14565b6000805b8280613fe3614ee6565b90508110156140e95783838281613ff8614ee6565b811061400057fe5b90600052602060002001614012614ee6565b14156140e157828181614023614ee6565b811061402b57fe5b90600052602060002001600090614040614f58565b5050826001848061404f614ee6565b9050038161405b614ee6565b811061406357fe5b90600052602060002001614075614ee6565b838281614080614ee6565b811061408857fe5b90600052602060002001819061409c614f58565b50505082806140a9614ee6565b906140d6907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830161525c565b506001915050610f52565b600101613fd9565b5060009392505050565b60008181526006602052806040812060009061410d614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416905080156141e4578073ffffffffffffffffffffffffffffffffffffffff1663668a0f026040518163ffffffff1660e01b81526004016020604051808303818680614175614fa6565b15801561418a57600080614187614e7b565b50505b505a614194614ff2565b50505050501580156141b3573d6000803e3d60006141b0614e7b565b50505b505050506040513d60208110156141d2576000806141cf614e7b565b50505b8101908080519450610ea89350505050565b6000838152600b602052604090206141fa614ee6565b915050610ea8565b6000600561420e614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a61424a61510a565b73ffffffffffffffffffffffffffffffffffffffff1614613fa95760405162461bcd60e51b815260040180806020018281038252602781526020018061531b60279139604001915050604051809103906121a7614e7b565b60008060006142b08661257d565b9150838614156142c45750839150806124c9565b6142cd8461257d565b905080156124c9576142e98161123b878563ffffffff613fab16565b925093509350939050565b60606001604051908082528060200260200182016040528015614321578160200160208202803883390190505b5090507f466c657869626c6553746f7261676500000000000000000000000000000000008160008151811061435257fe5b60200260200101818152505090565b60608151835101604051908082528060200260200182016040528015614391578160200160208202803883390190505b50905060005b83518110156143d3578381815181106143ac57fe5b60200260200101518282815181106143c057fe5b6020908102919091010152600101614397565b5060005b8251811015614416578281815181106143ec57fe5b602002602001015182828651018151811061440357fe5b60209081029190910101526001016143d7565b5092915050565b60006144276150dd565b600083815260096020526040902060405160a0810160405290818161444a614ee6565b81526020016001820161445b614ee6565b81526020016002820161446c614ee6565b815260200160006003830161447f614ee6565b60ff6101009290920a900416151581526020016001600383016144a0614ee6565b60ff6101009290920a900416151590525090506060810151806132d7575080608001519392505050565b6000826144d957506000610f52565b828202828482816144e657fe5b04146132d75760405162461bcd60e51b81526004018080602001828103825260218152602001806153716021913960400191505060405180910390614529614e7b565b50509392505050565b60006110de7f45786368616e6765720000000000000000000000000000000000000000000000614b46565b600082518451146145a85760405162461bcd60e51b815260040180806020018281038252603881526020018061539260389139604001915050604051809103906145a5614e7b565b50505b6102585a6145b4615216565b0182106146105760405162461bcd60e51b815260206004820152601f60248201527f54696d6520697320746f6f2066617220696e746f20746865206675747572650060448201526064016040518091039061460d614e7b565b50505b60005b845181101561473257600085828151811061462a57fe5b6020026020010151905084828151811061464057fe5b602002602001015161468c5760405162461bcd60e51b81526004018080602001828103825260398152602001806154516039913960400191505060405180910390614689614e7b565b50505b807f735553440000000000000000000000000000000000000000000000000000000014156146f45760405162461bcd60e51b81526004018080602001828103825260318152602001806152ea60319139604001915050604051809103906146f1614e7b565b50505b6146fd816132de565b84101561470a575061472a565b6147288186848151811061471a57fe5b602002602001015186614c60565b505b600101614613565b507f1bc0fc8997efa076f59b5ef02c315bc5390f7a6d24d661ce12128c01a3b0ba578484604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561479a578082015183820152602001614782565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156147d95780820151838201526020016147c1565b5050505090500194505050505060405180910390a15060019392505050565b60006110de7f466c657869626c6553746f726167650000000000000000000000000000000000614b46565b6000808212156148825760405162461bcd60e51b815260206004820152601b60248201527f4e656761746976652072617465206e6f7420737570706f72746564000000000060448201526064016040518091039061487f614e7b565b50505b600083815260076020526040812060009061489b614ee6565b906101000a900460ff1660ff1611156118e557600083815260076020526148de6012604083206000906148cc614ee6565b906101000a900460ff1660ff16614da4565b600a0a90506148f3838263ffffffff6144ca16565b915050610f52565b60006149056150dd565b600085815260096020526040902060405160a08101604052908181614928614ee6565b815260200160018201614939614ee6565b81526020016002820161494a614ee6565b815260200160006003830161495d614ee6565b60ff6101009290920a9004161515815260200160016003830161497e614ee6565b60ff6101009290920a900416151590525090508051158061499d575083155b156149ab57839150506132d7565b6000858152600c602052849250604081206149c4614ee6565b90508084101580156149d7575081606001515b156149e85781602001519250614529565b8084101580156149f9575081608001515b15614a0a5781604001519250614529565b6000614a1f600284519063ffffffff6144ca16565b9050858111614a315760009350614a44565b614a41818763ffffffff614da416565b93505b82602001518410614a5b5782602001519350614a6e565b82604001518411614a6e57826040015193505b5050509392505050565b6000828201838110156132d75760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015260640160405180910390614529614e7b565b600080600a8304614aee868663ffffffff6144ca16565b81614af557fe5b0490506005600a825b0610614b0857600a015b600a9004949350505050565b600080614b3a84614b2e87600a870263ffffffff6144ca16565b9063ffffffff614e0916565b90506005600a82614afe565b600081815260036020528060408120600090614b60614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a9004169050801515836040517f4d697373696e6720616464726573733a2000000000000000000000000000000060208201526031810191909152605101604051602081830303815290604052906144165760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614c16578082015183820152602001614bfe565b50505050905090810190601f168015614c435780820380516001836020036101000a031916815260200191505b509250505060405180910390614c57614e7b565b50505092915050565b6000838152600b60205260409020600081614c79614ee6565b91600183019150614c88614f58565b505050604051604080820181527affffffffffffffffffffffffffffffffffffffffffffffffffffff8416825264ffffffffff831660208084019190915260008681526004909152206000858152600b60205260408120614ce7614ee6565b8152602001908152602001600020815181600181614d03614ee6565b817affffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837affffffffffffffffffffffffffffffffffffffffffffffffffffff16021790614d4d614f58565b5050506020820151817b0100000000000000000000000000000000000000000000000000000081614d7c614ee6565b8164ffffffffff021916908364ffffffffff16021790614d9a614f58565b5050505050505050565b600082821115614e035760405162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015260640160405180910390614e00614e7b565b50505b50900390565b6000808211614e675760405162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015260640160405180910390614e64614e7b565b50505b6000828481614e7257fe5b04949350505050565b632a2a7adb598160e01b8152600481016020815285602082015260005b86811015614eb3578086015182820160400152602001614e98565b506020828760640184336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52505050565b6303daa959598160e01b8152836004820152602081602483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c528051935060005b60408110156116cc57600082820152602001614f2a565b604051604080820190526000808252602082015290565b6322bd64c0598160e01b8152836004820152846024820152600081604483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52600081526020614f2a565b638435035b598160e01b8152836004820152602081602483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c5280516000825293506020614f2a565b638540661f598160e01b8152615023565b8080831115610f52575090919050565b8080831015610f52575090919050565b836004820152846024820152606060448201528660648201526084810160005b8881101561505b578088015182820152602001615043565b506060828960a40184336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52815160408301513d6000853e8b8b82606087013350600060045af150596150b08d3d615013565b8c016150bc8187615003565b5b828110156150d157600081526020016150bd565b50929c50505050505050565b60405160a08101604090815260008083526020830181905290820181905260608201819052608082015290565b6373509064598160e01b8152602081600483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c5280516000825293506020614f2a565b6385979f76598160e01b8152836004820152846024820152606060448201528760648201526084810160005b8981101561519457808901518282015260200161517c565b506060828a60a40184336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52815160408301513d6000853e8c8c82606087013350600060045af150596151e98e3d615013565b8d016151f58187615003565b5b8281101561520a57600081526020016151f6565b50929d50505050505050565b63bdbf8c36598160e01b8152602081600483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c5280516000825293506020614f2a565b81615265614ee6565b818361526f614f58565b5050818111156116cc57818360005260206000206116cc92810191016110e191905b808211156152b057600080826152a5614f58565b505050600101615291565b509056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e65727368697052617465206f6620735553442063616e6e6f7420626520757064617465642c206974277320616c7761797320554e49542e4f6e6c7920746865206f7261636c652063616e20706572666f726d207468697320616374696f6e4f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743757272656e6379206b6579206172726179206c656e677468206d757374206d61746368207261746573206172726179206c656e6774682e6c6f7765724c696d6974206d7573742062652062656c6f772074686520656e747279506f696e7475707065724c696d6974206d757374206265206c657373207468616e20646f75626c6520656e747279506f696e7441676772656761746f7220646563696d616c732073686f756c64206265206c6f776572206f7220657175616c20746f2031385a65726f206973206e6f7420612076616c696420726174652c20706c656173652063616c6c2064656c6574655261746520696e73746561642e75707065724c696d6974206d7573742062652061626f76652074686520656e747279506f696e74"; + // A fallback function that allows us to choose between deploying two different initCodes function deploy(uint256 selection) external { + bytes memory prefix = hex'600D380380600D6000396000f3'; bytes memory initCode; + console.log("selection", selection); if(selection == 0) { // the resulting deployed bytecode is 0x00 // do concat to be clear - initCode = hex'600D380380600D6000396000f300'; + bytes memory runtimeCode = hex'00'; + initCode = abi.encodePacked(prefix, runtimeCode); } else if(selection == 1){ - initCode = hex'600D380380600D6000396000f36020'; + initCode = abi.encodePacked(prefix, largeBytecode); } address addr = Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), initCode); diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 864c5a543..77520cb5d 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -223,7 +223,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { }) - it('Gas Benchmark: un-cached contract deployment', async () => { + it('Gas Benchmark: un-cached minimal contract deployment', async () => { // Set destination for first contract deployment await OVM_StateManager.putEmptyAccount( "0xf7a70a9ed665630eaaf9f7b40b71f01cbf65f73f" @@ -241,7 +241,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { ) }) - it('Gas Benchmark: deploying a cached contract', async () => { + it('Gas Benchmark: cached minimal contract deployment', async () => { // Set destination for second contract deployment await OVM_StateManager.putEmptyAccount( "0xd236d314fd67606dddb3885f1330cf9bd3c8dbea" @@ -260,5 +260,43 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { 'Gas cost has significantly decreased, consider updating the benchmark to reflect the change' ) }) + + it('Gas Benchmark: un-cached larger contract deployment ', async () => { + DUMMY_TRANSACTION.data = Helper_SimpleDeployer.interface.encodeFunctionData('deploy(uint256)', [1]) + // Set destination for first contract deployment + await OVM_StateManager.putEmptyAccount( + "0x2dbd79d558282f50005be8e44c90a2db31042b40" + ) + const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, OVM_StateManager.address) + await tx.wait() + const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed + console.log(` calculated gas cost of ${gasCost}`) + + const benchmark: number = 581_062 + expect(gasCost).to.be.lte(benchmark) + expect(gasCost).to.be.gte( + benchmark - 1_000, + 'Gas cost has significantly decreased, consider updating the benchmark to reflect the change' + ) + }) + + it('Gas Benchmark: cached larger contract deployment ', async () => { + DUMMY_TRANSACTION.data = Helper_SimpleDeployer.interface.encodeFunctionData('deploy(uint256)', [1]) + // Set destination for first contract deployment + await OVM_StateManager.putEmptyAccount( + "0x7715813e9ee6baab3cb5ea89edc16fa92d526a74" + ) + const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, OVM_StateManager.address) + await tx.wait() + const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed + console.log(` calculated gas cost of ${gasCost}`) + + const benchmark: number = 581_062 + expect(gasCost).to.be.lte(benchmark) + expect(gasCost).to.be.gte( + benchmark - 1_000, + 'Gas cost has significantly decreased, consider updating the benchmark to reflect the change' + ) + }) }) }) From 57b8c86bd7e630842015ef35ed8c8c21e43a950c Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 15:37:34 -0500 Subject: [PATCH 32/39] failing to deploy large bytecode --- .../OVM/execution/OVM_ExecutionManager.sol | 2 - .../OVM/execution/OVM_SafetyCache.sol | 3 + .../OVM/execution/OVM_StateManager.sol | 738 ++++++++++++++++++ .../test-helpers/Helper_SimpleOvmDeployer.sol | 4 +- 4 files changed, 743 insertions(+), 4 deletions(-) create mode 100644 contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol index c5b2994c0..fd42c8cc5 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_ExecutionManager.sol @@ -3,7 +3,6 @@ pragma solidity >0.5.0 <0.8.0; pragma experimental ABIEncoderV2; -import "hardhat/console.sol"; /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; @@ -808,7 +807,6 @@ contract OVM_ExecutionManager is iOVM_ExecutionManager, Lib_AddressResolver { // some existing contract. On L1, users will prove that no contract exists at the address // and the OVM_FraudVerifier will populate the code hash of this address with a special // value that represents "known to be an empty account." - console.log(_address); if (_hasEmptyAccount(_address) == false) { _revertWithFlag(RevertFlag.CREATE_COLLISION); } diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol index 099434ed5..76c8464a6 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity >0.5.0 <0.8.0; +import "hardhat/console.sol"; + /* Library Imports */ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; @@ -70,6 +72,7 @@ contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { bool ) { bytes32 codehash = keccak256(abi.encode(_code)); + console.logBytes32(codehash); if(isSafeCodehash[codehash] == true) { return true; } diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol new file mode 100644 index 000000000..2d8a95bc1 --- /dev/null +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_StateManager.sol @@ -0,0 +1,738 @@ +// SPDX-License-Identifier: MIT +pragma solidity >0.5.0 <0.8.0; +pragma experimental ABIEncoderV2; + +/* Library Imports */ +import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; + +/* Interface Imports */ +import { iOVM_StateManager } from "../../iOVM/execution/iOVM_StateManager.sol"; + +/** + * @title OVM_StateManager + * @dev The State Manager contract holds all storage values for contracts in the OVM. It can only be written to by the + * the Execution Manager and State Transitioner. It runs on L1 during the setup and execution of a fraud proof. + * The same logic runs on L2, but has been implemented as a precompile in the L2 go-ethereum client + * (see https://github.com/ethereum-optimism/go-ethereum/blob/master/core/vm/ovm_state_manager.go). + * + * Compiler used: solc + * Runtime target: EVM + */ +contract OVM_StateManager is iOVM_StateManager { + + /************* + * Constants * + *************/ + + bytes32 constant internal EMPTY_ACCOUNT_STORAGE_ROOT = 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421; + bytes32 constant internal EMPTY_ACCOUNT_CODE_HASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; + bytes32 constant internal STORAGE_XOR_VALUE = 0xFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEFFEEDFACECAFEBEEF; + + + /************* + * Variables * + *************/ + + address override public owner; + address override public ovmExecutionManager; + mapping (address => Lib_OVMCodec.Account) internal accounts; + mapping (address => mapping (bytes32 => bytes32)) internal contractStorage; + mapping (address => mapping (bytes32 => bool)) internal verifiedContractStorage; + mapping (bytes32 => ItemState) internal itemStates; + uint256 internal totalUncommittedAccounts; + uint256 internal totalUncommittedContractStorage; + + + /*************** + * Constructor * + ***************/ + + /** + * @param _owner Address of the owner of this contract. + */ + constructor( + address _owner + ) + { + owner = _owner; + } + + + /********************** + * Function Modifiers * + **********************/ + + /** + * Simple authentication, this contract should only be accessible to the owner (which is expected to be the State Transitioner during `PRE_EXECUTION` + * or the OVM_ExecutionManager during transaction execution. + */ + modifier authenticated() { + // owner is the State Transitioner + require( + msg.sender == owner || msg.sender == ovmExecutionManager, + "Function can only be called by authenticated addresses" + ); + _; + } + + /******************** + * Public Functions * + ********************/ + + /** + * Checks whether a given address is allowed to modify this contract. + * @param _address Address to check. + * @return Whether or not the address can modify this contract. + */ + function isAuthenticated( + address _address + ) + override + public + view + returns ( + bool + ) + { + return (_address == owner || _address == ovmExecutionManager); + } + + /** + * Sets the address of the OVM_ExecutionManager. + * @param _ovmExecutionManager Address of the OVM_ExecutionManager. + */ + function setExecutionManager( + address _ovmExecutionManager + ) + override + public + authenticated + { + ovmExecutionManager = _ovmExecutionManager; + } + + /** + * Inserts an account into the state. + * @param _address Address of the account to insert. + * @param _account Account to insert for the given address. + */ + function putAccount( + address _address, + Lib_OVMCodec.Account memory _account + ) + override + public + authenticated + { + accounts[_address] = _account; + } + + /** + * Marks an account as empty. + * @param _address Address of the account to mark. + */ + function putEmptyAccount( + address _address + ) + override + public + authenticated + { + Lib_OVMCodec.Account storage account = accounts[_address]; + account.storageRoot = EMPTY_ACCOUNT_STORAGE_ROOT; + account.codeHash = EMPTY_ACCOUNT_CODE_HASH; + } + + /** + * Retrieves an account from the state. + * @param _address Address of the account to retrieve. + * @return Account for the given address. + */ + function getAccount( + address _address + ) + override + public + view + returns ( + Lib_OVMCodec.Account memory + ) + { + return accounts[_address]; + } + + /** + * Checks whether the state has a given account. + * @param _address Address of the account to check. + * @return Whether or not the state has the account. + */ + function hasAccount( + address _address + ) + override + public + view + returns ( + bool + ) + { + return accounts[_address].codeHash != bytes32(0); + } + + /** + * Checks whether the state has a given known empty account. + * @param _address Address of the account to check. + * @return Whether or not the state has the empty account. + */ + function hasEmptyAccount( + address _address + ) + override + public + view + returns ( + bool + ) + { + return ( + accounts[_address].codeHash == EMPTY_ACCOUNT_CODE_HASH + && accounts[_address].nonce == 0 + ); + } + + /** + * Sets the nonce of an account. + * @param _address Address of the account to modify. + * @param _nonce New account nonce. + */ + function setAccountNonce( + address _address, + uint256 _nonce + ) + override + public + authenticated + { + accounts[_address].nonce = _nonce; + } + + /** + * Gets the nonce of an account. + * @param _address Address of the account to access. + * @return Nonce of the account. + */ + function getAccountNonce( + address _address + ) + override + public + view + returns ( + uint256 + ) + { + return accounts[_address].nonce; + } + + /** + * Retrieves the Ethereum address of an account. + * @param _address Address of the account to access. + * @return Corresponding Ethereum address. + */ + function getAccountEthAddress( + address _address + ) + override + public + view + returns ( + address + ) + { + return accounts[_address].ethAddress; + } + + /** + * Retrieves the storage root of an account. + * @param _address Address of the account to access. + * @return Corresponding storage root. + */ + function getAccountStorageRoot( + address _address + ) + override + public + view + returns ( + bytes32 + ) + { + return accounts[_address].storageRoot; + } + + /** + * Initializes a pending account (during CREATE or CREATE2) with the default values. + * @param _address Address of the account to initialize. + */ + function initPendingAccount( + address _address + ) + override + public + authenticated + { + Lib_OVMCodec.Account storage account = accounts[_address]; + account.nonce = 1; + account.storageRoot = EMPTY_ACCOUNT_STORAGE_ROOT; + account.codeHash = EMPTY_ACCOUNT_CODE_HASH; + account.isFresh = true; + } + + /** + * Finalizes the creation of a pending account (during CREATE or CREATE2). + * @param _address Address of the account to finalize. + * @param _ethAddress Address of the account's associated contract on Ethereum. + * @param _codeHash Hash of the account's code. + */ + function commitPendingAccount( + address _address, + address _ethAddress, + bytes32 _codeHash + ) + override + public + authenticated + { + Lib_OVMCodec.Account storage account = accounts[_address]; + account.ethAddress = _ethAddress; + account.codeHash = _codeHash; + } + + /** + * Checks whether an account has already been retrieved, and marks it as retrieved if not. + * @param _address Address of the account to check. + * @return Whether or not the account was already loaded. + */ + function testAndSetAccountLoaded( + address _address + ) + override + public + authenticated + returns ( + bool + ) + { + return _testAndSetItemState( + _getItemHash(_address), + ItemState.ITEM_LOADED + ); + } + + /** + * Checks whether an account has already been modified, and marks it as modified if not. + * @param _address Address of the account to check. + * @return Whether or not the account was already modified. + */ + function testAndSetAccountChanged( + address _address + ) + override + public + authenticated + returns ( + bool + ) + { + return _testAndSetItemState( + _getItemHash(_address), + ItemState.ITEM_CHANGED + ); + } + + /** + * Attempts to mark an account as committed. + * @param _address Address of the account to commit. + * @return Whether or not the account was committed. + */ + function commitAccount( + address _address + ) + override + public + authenticated + returns ( + bool + ) + { + bytes32 item = _getItemHash(_address); + if (itemStates[item] != ItemState.ITEM_CHANGED) { + return false; + } + + itemStates[item] = ItemState.ITEM_COMMITTED; + totalUncommittedAccounts -= 1; + + return true; + } + + /** + * Increments the total number of uncommitted accounts. + */ + function incrementTotalUncommittedAccounts() + override + public + authenticated + { + totalUncommittedAccounts += 1; + } + + /** + * Gets the total number of uncommitted accounts. + * @return Total uncommitted accounts. + */ + function getTotalUncommittedAccounts() + override + public + view + returns ( + uint256 + ) + { + return totalUncommittedAccounts; + } + + /** + * Checks whether a given account was changed during execution. + * @param _address Address to check. + * @return Whether or not the account was changed. + */ + function wasAccountChanged( + address _address + ) + override + public + view + returns ( + bool + ) + { + bytes32 item = _getItemHash(_address); + return itemStates[item] >= ItemState.ITEM_CHANGED; + } + + /** + * Checks whether a given account was committed after execution. + * @param _address Address to check. + * @return Whether or not the account was committed. + */ + function wasAccountCommitted( + address _address + ) + override + public + view + returns ( + bool + ) + { + bytes32 item = _getItemHash(_address); + return itemStates[item] >= ItemState.ITEM_COMMITTED; + } + + + /************************************ + * Public Functions: Storage Access * + ************************************/ + + /** + * Changes a contract storage slot value. + * @param _contract Address of the contract to modify. + * @param _key 32 byte storage slot key. + * @param _value 32 byte storage slot value. + */ + function putContractStorage( + address _contract, + bytes32 _key, + bytes32 _value + ) + override + public + authenticated + { + // A hilarious optimization. `SSTORE`ing a value of `bytes32(0)` is common enough that it's + // worth populating this with a non-zero value in advance (during the fraud proof + // initialization phase) to cut the execution-time cost down to 5000 gas. + contractStorage[_contract][_key] = _value ^ STORAGE_XOR_VALUE; + + // Only used when initially populating the contract storage. OVM_ExecutionManager will + // perform a `hasContractStorage` INVALID_STATE_ACCESS check before putting any contract + // storage because writing to zero when the actual value is nonzero causes a gas + // discrepancy. Could be moved into a new `putVerifiedContractStorage` function, or + // something along those lines. + if (verifiedContractStorage[_contract][_key] == false) { + verifiedContractStorage[_contract][_key] = true; + } + } + + /** + * Retrieves a contract storage slot value. + * @param _contract Address of the contract to access. + * @param _key 32 byte storage slot key. + * @return 32 byte storage slot value. + */ + function getContractStorage( + address _contract, + bytes32 _key + ) + override + public + view + returns ( + bytes32 + ) + { + // Storage XOR system doesn't work for newly created contracts that haven't set this + // storage slot value yet. + if ( + verifiedContractStorage[_contract][_key] == false + && accounts[_contract].isFresh + ) { + return bytes32(0); + } + + // See `putContractStorage` for more information about the XOR here. + return contractStorage[_contract][_key] ^ STORAGE_XOR_VALUE; + } + + /** + * Checks whether a contract storage slot exists in the state. + * @param _contract Address of the contract to access. + * @param _key 32 byte storage slot key. + * @return Whether or not the key was set in the state. + */ + function hasContractStorage( + address _contract, + bytes32 _key + ) + override + public + view + returns ( + bool + ) + { + return verifiedContractStorage[_contract][_key] || accounts[_contract].isFresh; + } + + /** + * Checks whether a storage slot has already been retrieved, and marks it as retrieved if not. + * @param _contract Address of the contract to check. + * @param _key 32 byte storage slot key. + * @return Whether or not the slot was already loaded. + */ + function testAndSetContractStorageLoaded( + address _contract, + bytes32 _key + ) + override + public + authenticated + returns ( + bool + ) + { + return _testAndSetItemState( + _getItemHash(_contract, _key), + ItemState.ITEM_LOADED + ); + } + + /** + * Checks whether a storage slot has already been modified, and marks it as modified if not. + * @param _contract Address of the contract to check. + * @param _key 32 byte storage slot key. + * @return Whether or not the slot was already modified. + */ + function testAndSetContractStorageChanged( + address _contract, + bytes32 _key + ) + override + public + authenticated + returns ( + bool + ) + { + return _testAndSetItemState( + _getItemHash(_contract, _key), + ItemState.ITEM_CHANGED + ); + } + + /** + * Attempts to mark a storage slot as committed. + * @param _contract Address of the account to commit. + * @param _key 32 byte slot key to commit. + * @return Whether or not the slot was committed. + */ + function commitContractStorage( + address _contract, + bytes32 _key + ) + override + public + authenticated + returns ( + bool + ) + { + bytes32 item = _getItemHash(_contract, _key); + if (itemStates[item] != ItemState.ITEM_CHANGED) { + return false; + } + + itemStates[item] = ItemState.ITEM_COMMITTED; + totalUncommittedContractStorage -= 1; + + return true; + } + + /** + * Increments the total number of uncommitted storage slots. + */ + function incrementTotalUncommittedContractStorage() + override + public + authenticated + { + totalUncommittedContractStorage += 1; + } + + /** + * Gets the total number of uncommitted storage slots. + * @return Total uncommitted storage slots. + */ + function getTotalUncommittedContractStorage() + override + public + view + returns ( + uint256 + ) + { + return totalUncommittedContractStorage; + } + + /** + * Checks whether a given storage slot was changed during execution. + * @param _contract Address to check. + * @param _key Key of the storage slot to check. + * @return Whether or not the storage slot was changed. + */ + function wasContractStorageChanged( + address _contract, + bytes32 _key + ) + override + public + view + returns ( + bool + ) + { + bytes32 item = _getItemHash(_contract, _key); + return itemStates[item] >= ItemState.ITEM_CHANGED; + } + + /** + * Checks whether a given storage slot was committed after execution. + * @param _contract Address to check. + * @param _key Key of the storage slot to check. + * @return Whether or not the storage slot was committed. + */ + function wasContractStorageCommitted( + address _contract, + bytes32 _key + ) + override + public + view + returns ( + bool + ) + { + bytes32 item = _getItemHash(_contract, _key); + return itemStates[item] >= ItemState.ITEM_COMMITTED; + } + + + /********************** + * Internal Functions * + **********************/ + + /** + * Generates a unique hash for an address. + * @param _address Address to generate a hash for. + * @return Unique hash for the given address. + */ + function _getItemHash( + address _address + ) + internal + pure + returns ( + bytes32 + ) + { + return keccak256(abi.encodePacked(_address)); + } + + /** + * Generates a unique hash for an address/key pair. + * @param _contract Address to generate a hash for. + * @param _key Key to generate a hash for. + * @return Unique hash for the given pair. + */ + function _getItemHash( + address _contract, + bytes32 _key + ) + internal + pure + returns ( + bytes32 + ) + { + return keccak256(abi.encodePacked( + _contract, + _key + )); + } + + /** + * Checks whether an item is in a particular state (ITEM_LOADED or ITEM_CHANGED) and sets the + * item to the provided state if not. + * @param _item 32 byte item ID to check. + * @param _minItemState Minimum state that must be satisfied by the item. + * @return Whether or not the item was already in the state. + */ + function _testAndSetItemState( + bytes32 _item, + ItemState _minItemState + ) + internal + returns ( + bool + ) + { + bool wasItemState = itemStates[_item] >= _minItemState; + + if (wasItemState == false) { + itemStates[_item] = _minItemState; + } + + return wasItemState; + } +} diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol index 2578021b5..b37646de6 100644 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -8,6 +8,7 @@ import "hardhat/console.sol"; contract Helper_SimpleOvmDeployer { + // bytecode from "ExchangeRates.sol" as used by Synthetix bytes constant largeBytecode = hex"608060405234801561001957600080610016614e7b565b50505b506004361061031d5760003560e01c8063654a60ac116101b0578063935f4abd116100f7578063c2c8a676116100a0578063ce8480ea1161007a578063ce8480ea14610e1a578063de02795e14610e40578063fdadbc7e14610e665761031d565b8063c2c8a67614610c70578063c8e5bbd514610d04578063c8e6f39514610df45761031d565b8063b199c764116100d1578063b199c76414610aeb578063b295ad3414610b33578063bfa005ce14610b6f5761031d565b8063935f4abd14610a79578063ac82f60814610a9f578063af3aea8614610ac55761031d565b80637adbf973116101595780638295016a116101335780638295016a14610a13578063899ffef414610a695780638da5cb5b14610a715761031d565b80637adbf973146109a95780637dc0d1d0146109e55780637f6e9d15146109ed5761031d565b8063741853601161018a578063741853601461097357806379ba50971461097b5780637a018a1e146109835761031d565b8063654a60ac146108c25780637103353e146108f4578063728dec291461091a5761031d565b80632af64bd3116102745780633f0e084f1161021d5780634c36b837116101f75780634c36b8371461088c5780634f72def61461089457806353a47bb7146108ba5761031d565b80633f0e084f146107e65780634308a94f1461082857806345938849146108665761031d565b80632ea913d41161024e5780632ea913d4146107745780633375fcd11461079a57806338aa1b99146107c05761031d565b80632af64bd3146106815780632bed9e0c146106895780632d7371e1146106af5761031d565b80630ee4951b116102d65780632528f0fe116102b05780632528f0fe146105e1578063266da16b146106075780632678df96146106455761031d565b80630ee4951b14610551578063109e46a21461056b5780631627540c146105a35761031d565b806305a046e51161030757806305a046e5146103965780630a7d36d11461047d5780630c71cd23146105115761031d565b80629919c01461032b57806304f3bcec14610365575b600080610328614e7b565b50505b6103516004803603602081101561034a57600080610347614e7b565b50505b5035610e92565b604051901515815260200160405180910390f35b61036d610ead565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61042a600480360360208110156103b5576000806103b2614e7b565b50505b8101906020810181356401000000008111156103d9576000806103d6614e7b565b50505b8201836020820111156103f4576000806103f1614e7b565b50505b8035906020019184602083028401116401000000008311171561041f5760008061041c614e7b565b50505b509092509050610ed9565b60405160208082528190810183818151815260200191508051906020019060200280838360005b83811015610469578082015183820152602001610451565b505050509050019250505060405180910390f35b6103516004803603602081101561049c57600080610499614e7b565b50505b8101906020810181356401000000008111156104c0576000806104bd614e7b565b50505b8201836020820111156104db576000806104d8614e7b565b50505b8035906020019184602083028401116401000000008311171561050657600080610503614e7b565b50505b509092509050610f58565b610537600480360360208110156105305760008061052d614e7b565b50505b503561100b565b604051918252151560208201526040908101905180910390f35b6105596110d4565b60405190815260200160405180910390f35b6105596004803603608081101561058a57600080610587614e7b565b50505b50803590602081013590604081013590606001356110e4565b6105df600480360360208110156105c2576000806105bf614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff16611127565b005b61035160048036036020811015610600576000806105fd614e7b565b50505b50356111c8565b610559600480360360a081101561062657600080610623614e7b565b50505b50803590602081013590604081013590606081013590608001356111e8565b61042a6004803603602081101561066457600080610661614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff16611255565b61035161136e565b6105df600480360360208110156106a8576000806106a5614e7b565b50505b5035611563565b6106db600480360360408110156106ce576000806106cb614e7b565b50505b50803590602001356116d1565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561071f578082015183820152602001610707565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561075e578082015183820152602001610746565b5050505090500194505050505060405180910390f35b6105596004803603602081101561079357600080610790614e7b565b50505b50356117c2565b610351600480360360208110156107b9576000806107b6614e7b565b50505b50356117ed565b610351600480360360208110156107df576000806107dc614e7b565b50505b50356118eb565b6105df6004803603604081101561080557600080610802614e7b565b50505b508035906020013573ffffffffffffffffffffffffffffffffffffffff166118f9565b61084e6004803603602081101561084757600080610844614e7b565b50505b5035611c94565b60405191825260208201526040908101905180910390f35b6105df6004803603602081101561088557600080610882614e7b565b50505b5035611ce1565b61036d611e78565b610559600480360360208110156108b3576000806108b0614e7b565b50505b5035611e82565b61036d611e8e565b610559600480360360608110156108e1576000806108de614e7b565b50505b5080359060208101359060400135611e9a565b61036d6004803603602081101561091357600080610910614e7b565b50505b5035611eb2565b6109406004803603602081101561093957600080610936614e7b565b50505b5035611ecc565b604051948552602085019390935260408085019290925215156060840152901515608083015260a0909101905180910390f35b6105df611f37565b6105df6121ab565b610559600480360360208110156109a25760008061099f614e7b565b50505b50356123b8565b6105df600480360360208110156109c8576000806109c5614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff166123c3565b61036d61248e565b61055960048036036020811015610a0c57600080610a09614e7b565b50505b503561249a565b610a4560048036036060811015610a3257600080610a2f614e7b565b50505b50803590602081013590604001356124b2565b60405180848152602001838152602001828152602001935050505060405180910390f35b61042a6124d2565b61036d61255a565b61055960048036036020811015610a9857600080610a95614e7b565b50505b5035612565565b61055960048036036020811015610abe57600080610abb614e7b565b50505b503561257d565b61035160048036036020811015610ae457600080610ae1614e7b565b50505b50356125ac565b6105df600480360360c0811015610b0a57600080610b07614e7b565b50505b50803590602081013590604081013590606081013590608081013515159060a0013515156125b7565b610b5960048036036020811015610b5257600080610b4f614e7b565b50505b5035612aaf565b60405160ff909116815260200160405180910390f35b61035160048036036060811015610b8e57600080610b8b614e7b565b50505b810190602081018135640100000000811115610bb257600080610baf614e7b565b50505b820183602082011115610bcd57600080610bca614e7b565b50505b80359060200191846020830284011164010000000083111715610bf857600080610bf5614e7b565b50505b919390929091602081019035640100000000811115610c1f57600080610c1c614e7b565b50505b820183602082011115610c3a57600080610c37614e7b565b50505b80359060200191846020830284011164010000000083111715610c6557600080610c62614e7b565b50505b919350915035612ad6565b61042a60048036036020811015610c8f57600080610c8c614e7b565b50505b810190602081018135640100000000811115610cb357600080610cb0614e7b565b50505b820183602082011115610cce57600080610ccb614e7b565b50505b80359060200191846020830284011164010000000083111715610cf957600080610cf6614e7b565b50505b509092509050612b5d565b610d9860048036036020811015610d2357600080610d20614e7b565b50505b810190602081018135640100000000811115610d4757600080610d44614e7b565b50505b820183602082011115610d6257600080610d5f614e7b565b50505b80359060200191846020830284011164010000000083111715610d8d57600080610d8a614e7b565b50505b509092509050612bd2565b604051811515602082015260408082528190810184818151815260200191508051906020019060200280838360005b83811015610ddf578082015183820152602001610dc7565b50505050905001935050505060405180910390f35b6105df60048036036020811015610e1357600080610e10614e7b565b50505b5035612d40565b61055960048036036020811015610e3957600080610e36614e7b565b50505b5035612ea3565b6105df60048036036020811015610e5f57600080610e5c614e7b565b50505b5035612eae565b61084e60048036036040811015610e8557600080610e82614e7b565b50505b508035906020013561315a565b6000610ea582610ea0613172565b613293565b90505b919050565b60006002610eb9614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60608082604051908082528060200260200182016040528015610f06578160200160208202803883390190505b50905060005b83811015610f4e57610f2f858583818110610f2357fe5b905060200201356132de565b828281518110610f3b57fe5b6020908102919091010152600101610f0c565b5090505b92915050565b600080610f63613172565b90506060610fa38585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132fa92505050565b905060005b84811015610fff57818181518110610fbc57fe5b602002602001015180610fe65750610fe6868683818110610fd957fe5b9050602002013584613293565b15610ff75760019350505050610f52565b600101610fa8565b50600095945050505050565b600080611016614f41565b61101f846135e4565b9050837f735553440000000000000000000000000000000000000000000000000000000014156110755780517affffffffffffffffffffffffffffffffffffffffffffffffffffff169250600091506110cf9050565b8051611093611082613172565b836020015164ffffffffff16613985565b806110aa57506110aa856110a56139a8565b613a5e565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff90911693509150505b915091565b60006110de613172565b90505b90565b600083815b6110f68783600101613be4565b915050801580611107575083850181115b156111145750905061111f565b6001909101906110e9565b949350505050565b61112f613f0a565b806001808061113c614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790611178614f58565b5050507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce228160405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b60006111d682610ea0613172565b80610ea55750610ea5826110a56139a8565b6000838614156111f957508361124c565b60006112058785613be4565b50905060006112148685613be4565b509050806112275760009250505061124c565b6112478161123b898563ffffffff613fab16565b9063ffffffff613fc016565b925050505b95945050505050565b60606000600880611264614ee6565b905060405190808252806020026020018201604052801561128f578160200160208202803883390190505b50915060005b6008806112a0614ee6565b9050811015611367576000600882816112b7614ee6565b81106112bf57fe5b906000526020600020016112d1614ee6565b6000818152600660205290915073ffffffffffffffffffffffffffffffffffffffff86169060409020600090611305614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561135e578084848060010195508151811061135157fe5b6020026020010181815250505b50600101611295565b5050919050565b6000606061137a6124d2565b905060005b815181101561155a57600082828151811061139657fe5b602002602001015160008181526003602052909150604090206000906113ba614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416600060026113e5614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166321f8a721836040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815260048101919091526024016020604051808303818680611468614fa6565b15801561147d5760008061147a614e7b565b50505b505a611487614ff2565b50505050501580156114a6573d6000803e3d60006114a3614e7b565b50505b505050506040513d60208110156114c5576000806114c2614e7b565b50505b81019080805173ffffffffffffffffffffffffffffffffffffffff169390931415925082915061154090505750600081815260036020526040812060009061150b614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b1561155157600093505050506110e1565b5060010161137f565b50600191505090565b61156b613f0a565b6000818152600660205260408120600090611584614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a9004169050806115ff5760405162461bcd60e51b815260206004820152601c60248201527f4e6f2061676772656761746f722065786973747320666f72206b6579000000006044820152606401604051809103906115fc614e7b565b50505b6000828152600660205260409020600181611618614ee6565b9073ffffffffffffffffffffffffffffffffffffffff0219169061163a614f58565b50506000828152600760205260409020600181611655614ee6565b9060ff02191690611664614f58565b50506000611673836008613fd5565b905080156116cc577fec70e890fc7db7de4059b114c9093a1f41283d18ffcfbcac45566feea4d4f777838360405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a15b505050565b606080826040519080825280602002602001820160405280156116fe578160200160208202803883390190505b5091508260405190808252806020026020018201604052801561172b578160200160208202803883390190505b5090506000611739856140f3565b905060005b848110156117b8576117508683613be4565b85838151811061175c57fe5b6020026020010185848151811061176f57fe5b6020908102919091010191909152528161178b57506117bb9050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019060010161173e565b50505b9250929050565b600a81816117ce614ee6565b81106117d657fe5b9060005260206000200190506117ea614ee6565b81565b60006117f76150dd565b600083815260096020526040902060405160a0810160405290818161181a614ee6565b81526020016001820161182b614ee6565b81526020016002820161183c614ee6565b815260200160006003830161184f614ee6565b60ff6101009290920a90041615158152602001600160038301611870614ee6565b60ff6101009290920a9004161515905250905080511580611892575080606001515b8061189e575080608001515b156118ad576000915050610ea8565b60006118b88461257d565b90506000811180156118dc57508160200151811015806118dc575081604001518111155b92505050610ea8565b50919050565b6000610ea5826110a56139a8565b611901613f0a565b80600073ffffffffffffffffffffffffffffffffffffffff821663668a0f026040518163ffffffff1660e01b81526004016020604051808303818680611945614fa6565b15801561195a57600080611957614e7b565b50505b505a611964614ff2565b5050505050158015611983573d6000803e3d6000611980614e7b565b50505b505050506040513d60208110156119a25760008061199f614e7b565b50505b81019080805193909310159250611a0b9150505760405162461bcd60e51b815260206004820152601b60248201527f476976656e2041676772656761746f7220697320696e76616c69640000000000604482015260640160405180910390611a08614e7b565b50505b60008173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b81526004016020604051808303818680611a4e614fa6565b158015611a6357600080611a60614e7b565b50505b505a611a6d614ff2565b5050505050158015611a8c573d6000803e3d6000611a89614e7b565b50505b505050506040513d6020811015611aab57600080611aa8614e7b565b50505b81019080805193505050601260ff831611159050611b035760405162461bcd60e51b815260040180806020018281038252603281526020018061541f6032913960400191505060405180910390611b00614e7b565b50505b6000848152600660205260408120600090611b1c614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611bb05783600880600181611b64614ee6565b018082611b6f614f58565b50506000928352917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830191506020902091929101611bac614f58565b5050505b60008481526006602052829060409020600181611bcb614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790611c07614f58565b50505060008481526007602052819060409020600181611c25614ee6565b8160ff021916908360ff16021790611c3b614f58565b5050507f0bcae573430f69c5361e5d76534d3f61d2d803958778680cd74be9dc6299bc63848360405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a150505050565b600080611c9f614f41565b611ca8846135e4565b9050805181602001517affffffffffffffffffffffffffffffffffffffffffffffffffffff909116935064ffffffffff16915050915091565b611ce9614202565b6000611cf48261257d565b11611d4e5760405162461bcd60e51b815260206004820152600c60248201527f52617465206973207a65726f0000000000000000000000000000000000000000604482015260640160405180910390611d4b614e7b565b50505b60008181526004602052604090206000828152600b60205260408120611d72614ee6565b8152602001908152602001600020600081600181611d8e614ee6565b907affffffffffffffffffffffffffffffffffffffffffffffffffffff02191690611db7614f58565b508290507b0100000000000000000000000000000000000000000000000000000081611de1614ee6565b9064ffffffffff02191690611df4614f58565b5050506000828152600b6020526040915020600081611e11614ee6565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019150611e3f614f58565b5050507fe69d655565c7ff1353d8eaeea62fb7904fa9696987431ec351be288c865f1ae18160405190815260200160405180910390a150565b60006110de6139a8565b600881816117ce614ee6565b60006001610eb9614ee6565b6000611ea78484846142a2565b509095945050505050565b600660205280600052604060002060009150610eb9614ee6565b6009602052806000526040600020905080611ee5614ee6565b9080600101611ef2614ee6565b9080600201611eff614ee6565b90600060038201611f0e614ee6565b906101000a900460ff169080600301600190611f28614ee6565b906101000a900460ff16905085565b6060611f416124d2565b905060005b81518110156121a7576000828281518110611f5d57fe5b602002602001015190506000806002611f74614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dacb2d0183846040517f5265736f6c766572206d697373696e67207461726765743a2000000000000000602082015260398101919091526059016040516020818303038152906040526040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561204357808201518382015260200161202b565b50505050905090810190601f1680156120705780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818680612089614fa6565b15801561209e5760008061209b614e7b565b50505b505a6120a8614ff2565b50505050501580156120c7573d6000803e3d60006120c4614e7b565b50505b505050506040513d60208110156120e6576000806120e3614e7b565b50505b810190808051600086815260036020529094508493506040925090502060018161210e614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179061214a614f58565b5050507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68828260405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a15050600101611f46565b5050565b600060016121b7614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a6121f361510a565b73ffffffffffffffffffffffffffffffffffffffff161461224e5760405162461bcd60e51b81526004018080602001828103825260358152602001806152b5603591396040019150506040518091039061224b614e7b565b50505b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c60008061227a614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660016000906122a4614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff9283168152911660208201526040908101905180910390a1600060016122fd614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a8161232a614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790612366614f58565b5050506000600160006101000a8161237c614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906116cc614f58565b6000610ea5826140f3565b6123cb613f0a565b8060056001816123d9614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790612415614f58565b5050507f3df77beb5db05fcdd70a30fc8adf3f83f9501b68579455adbd100b81809403946005600090612446614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b60006005610eb9614ee6565b600c60205280600052604060002090506117ea614ee6565b60008060006124c28686866142a2565b9250925092505b93509350939050565b6060806124dd6142f4565b90506060600160405190808252806020026020018201604052801561250c578160200160208202803883390190505b5090507f45786368616e67657200000000000000000000000000000000000000000000008160008151811061253d57fe5b6020026020010181815250506125538282614361565b9250505090565b600080610eb9614ee6565b600b60205280600052604060002090506117ea614ee6565b6000612588826135e4565b517affffffffffffffffffffffffffffffffffffffffffffffffffffff1692915050565b6000610ea58261441d565b6125bf613f0a565b6000831161261c5760405162461bcd60e51b815260206004820152601a60248201527f6c6f7765724c696d6974206d7573742062652061626f76652030000000000000604482015260640160405180910390612619614e7b565b50505b8484116126635760405162461bcd60e51b815260040180806020018281038252602781526020018061548a6027913960400191505060405180910390612660614e7b565b50505b61267485600263ffffffff6144ca16565b84106126ba5760405162461bcd60e51b815260040180806020018281038252602e8152602001806153f1602e9139604001915050604051809103906126b7614e7b565b50505b8483106127015760405162461bcd60e51b81526004018080602001828103825260278152602001806153ca60279139604001915050604051809103906126fe614e7b565b50505b81801561270b5750805b156127655760405162461bcd60e51b815260206004820152601c60248201527f43616e6e6f7420667265657a6520617420626f7468206c696d69747300000000604482015260640160405180910390612762614e7b565b50505b600086815260096020526040812090508061277e614ee6565b6127dd5786600a80600181612791614ee6565b01808261279c614f58565b50506000928352917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301915060209020919291016127d9614f58565b5050505b8580826127e8614f58565b505050848160010181906127fa614f58565b5050508381600201819061280c614f58565b50505082806128185750815b1561291957826003820160018161282d614ee6565b8160ff02191690831515021790612842614f58565b50839150506003820161010081612857614ee6565b8160ff0219169083151502179061286c614f58565b505050600061287a886140f3565b6000898152600c6020529091508190604090208190612897614f58565b5050507ff72828471e37526c68fd812a1fa6eeff993c3f81bd96c0242dc5b3e144145df088856128c757866128c9565b875b835a6128d361510a565b604051938452602084019290925260408084019190915273ffffffffffffffffffffffffffffffffffffffff90911660608301526080909101905180910390a150612989565b60006003820160018161292a614ee6565b8160ff0219169083151502179061293f614f58565b5060009150506003820161010081612955614ee6565b8160ff0219169083151502179061296a614f58565b5050506000878152600c602052604081208190612985614f58565b5050505b60006129948861257d565b90508015612a56576129a4614532565b73ffffffffffffffffffffffffffffffffffffffff1663ce09694089836040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526004810192909252602482015260440160006040518083038160008780612a12614fa6565b158015612a2757600080612a24614e7b565b50505b505a612a31615150565b505050505050158015612a51573d6000803e3d6000612a4e614e7b565b50505b505050505b7f37efb38e92b0f94698f6df0c9070e2f00946862a042ac09e34ae8c547684240a888888886040518085815260200184815260200183815260200182815260200194505050505060405180910390a15050505050505050565b600760205280600052604060002060009150612ac9614ee6565b906101000a900460ff1681565b6000612ae0614202565b612b53868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250889250879150819050602080820201604051908101604052809392919081815260200183836020028082843760009201919091525087925061455d915050565b9695505050505050565b60608082604051908082528060200260200182016040528015612b8a578160200160208202803883390190505b50905060005b83811015610f4e57612bb3858583818110612ba757fe5b9050602002013561257d565b828281518110612bbf57fe5b6020908102919091010152600101612b90565b6060600082604051908082528060200260200182016040528015612c00578160200160208202803883390190505b5091506000612c0d613172565b90506060612c4d8686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132fa92505050565b905060005b85811015612d3657612c62614f41565b612c7d888884818110612c7157fe5b905060200201356135e4565b905080517affffffffffffffffffffffffffffffffffffffffffffffffffffff16868381518110612caa57fe5b60200260200101818152505084158015612cf65750878783818110612ccb57fe5b905060200201357f735553440000000000000000000000000000000000000000000000000000000014155b15612d2d57828281518110612d0757fe5b602002602001015180612d2a5750612d2a84826020015164ffffffffff16613985565b94505b50600101612c52565b5050509250929050565b612d48613f0a565b6000818152600960205260408120612d5e614ee6565b11612db85760405162461bcd60e51b815260206004820152601860248201527f4e6f20696e766572746564207072696365206578697374730000000000000000604482015260640160405180910390612db5614e7b565b50505b600081815260096020526040902060008082612dd2614f58565b505060018201600090612de3614f58565b505060028201600090612df4614f58565b505060038201600181612e05614ee6565b9060ff02191690612e14614f58565b50506003820161010081612e26614ee6565b9060ff02191690612e35614f58565b505050506000612e4682600a613fd5565b905080156121a7577f37efb38e92b0f94698f6df0c9070e2f00946862a042ac09e34ae8c547684240a8260008060006040518085815260200184815260200183815260200182815260200194505050505060405180910390a15050565b6000610ea5826132de565b60008181526009602052604081209050600081612ec9614ee6565b11612f235760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f7420667265657a65206e6f6e2d696e766572736520726174650000604482015260640160405180910390612f20614e7b565b50505b600060038201612f31614ee6565b906101000a900460ff16158015612f5d5750600160038201612f51614ee6565b906101000a900460ff16155b612fb65760405162461bcd60e51b815260206004820152601a60248201527f546865207261746520697320616c72656164792066726f7a656e000000000000604482015260640160405180910390612fb3614e7b565b50505b6000612fc18361257d565b9050600081118015612ff3575081600101612fda614ee6565b81101580612ff3575081600201612fef614ee6565b8111155b156131015781600101613004614ee6565b811460038301600181613015614ee6565b8160ff0219169083151502179061302a614f58565b50505081600201613039614ee6565b8114600383016101008161304b614ee6565b8160ff02191690831515021790613060614f58565b505050600061306e846140f3565b6000858152600c602052909150819060409020819061308b614f58565b5050507ff72828471e37526c68fd812a1fa6eeff993c3f81bd96c0242dc5b3e144145df08483835a6130bb61510a565b604051938452602084019290925260408084019190915273ffffffffffffffffffffffffffffffffffffffff90911660608301526080909101905180910390a1506116cc565b60405162461bcd60e51b815260206004820152601260248201527f526174652077697468696e20626f756e64730000000000000000000000000000604482015260640160405180910390613153614e7b565b5050505050565b6000806131678484613be4565b915091509250929050565b600061317c6147f8565b73ffffffffffffffffffffffffffffffffffffffff166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f726174655374616c65506572696f6400000000000000000000000000000000006040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303818680613228614fa6565b15801561323d5760008061323a614e7b565b50505b505a613247614ff2565b5050505050158015613266573d6000803e3d6000613263614e7b565b50505b505050506040513d602081101561328557600080613282614e7b565b50505b810190808051935050505090565b6000827f735553440000000000000000000000000000000000000000000000000000000014156132c557506000610f52565b6132d7826132d2856132de565b613985565b9392505050565b60006132e9826135e4565b6020015164ffffffffff1692915050565b606060006133066139a8565b905073ffffffffffffffffffffffffffffffffffffffff8116156135b15760608351604051908082528060200260200182016040528015613351578160200160208202803883390190505b50905060005b84518110156133e7576006600086838151811061337057fe5b60200260200101518152602001908152602001600020600090613391614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff168282815181106133ba57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101613357565b508173ffffffffffffffffffffffffffffffffffffffff16637d723cac826040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b8381101561345457808201518382015260200161343c565b50505050905001925050506000604051808303818680613472614fa6565b15801561348757600080613484614e7b565b50505b505a613491614ff2565b50505050501580156134b0573d6000803e3d60006134ad614e7b565b50505b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526020811015613500576000806134fd614e7b565b50505b810190808051604051939291908464010000000082111561352957600080613526614e7b565b50505b90830190602082018581111561354757600080613544614e7b565b50505b825186602082028301116401000000008211171561356d5760008061356a614e7b565b50505b825250602001908051906020019060200280838360005b8381101561359c578082015183820152602001613584565b505050509050016040525050509250506118e5565b82516040519080825280602002602001820160405280156135dc578160200160208202803883390190505b509392505050565b6135ec614f41565b6000828152600660205260408120600090613605614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416905080156138775760606040516024016040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08183030181526040919091527ffeaf968c000000000000000000000000000000000000000000000000000000006020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909117905290506000606073ffffffffffffffffffffffffffffffffffffffff8416836040518082805190602001908083835b6020831061371957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016136dc565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855a613751614ff2565b50505050509150503d80600081146137a3576040513d603f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01681016040523d815291503d6000602084013e6137a8565b606091505b5091509150811561386f576000808060208401845160a08110156137d4576000806137d1614e7b565b50505b810190808051929190602001805192919060200180519291906020018051929190602001805150959850939650909450604093505050505180604001604052806138348b6138228d87614823565b8769ffffffffffffffffffff166148fb565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018264ffffffffff16815250975050505050505050610ea8565b5050506118e5565b6000838152600b6020526040812061388d614ee6565b9050613897614f41565b60008581526004602052604090206000838152602091909152604090206040516040808201905290816000826138cb614ee6565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff6101009290920a9004168152602001601b82613901614ee6565b64ffffffffff6101009290920a9004169052509050604051604080820190528061394a8784517affffffffffffffffffffffffffffffffffffffffffffffffffffff16866148fb565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff168152602001826020015164ffffffffff168152509350505050610ea8565b60005a613990615216565b6139a0838563ffffffff614a7816565b109392505050565b60006139b26147f8565b73ffffffffffffffffffffffffffffffffffffffff16639ee5955a7f53797374656d53657474696e67730000000000000000000000000000000000007f61676772656761746f725761726e696e67466c616773000000000000000000006040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303818680613228614fa6565b6000827f73555344000000000000000000000000000000000000000000000000000000001415613a9057506000610f52565b6000838152600660205260408120600090613aa9614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a9004169050801580613aeb575073ffffffffffffffffffffffffffffffffffffffff8316155b15613afa576000915050610f52565b8273ffffffffffffffffffffffffffffffffffffffff1663357e47fe826040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016020604051808303818680613b76614fa6565b158015613b8b57600080613b88614e7b565b50505b505a613b95614ff2565b5050505050158015613bb4573d6000803e3d6000613bb1614e7b565b50505b505050506040513d6020811015613bd357600080613bd0614e7b565b50505b810190808051979650505050505050565b60008281526006602052808060408120600090613bff614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a90041690508015613e395760608460405160248101919091526044016040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08183030181526040919091527f9a6fc8f5000000000000000000000000000000000000000000000000000000006020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909117905290506000606073ffffffffffffffffffffffffffffffffffffffff8416836040518082805190602001908083835b60208310613d1c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613cdf565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855a613d54614ff2565b50505050509150503d8060008114613da6576040513d603f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01681016040523d815291503d6000602084013e613dab565b606091505b50915091508115613e315760008060208301835160a0811015613dd657600080613dd3614e7b565b50505b8101908080519291906020018051929190602001805192919060200180519291906020018051906020019092919050505050935050925050613e228a613e1c8c85614823565b8b6148fb565b975095506117bb945050505050565b505050613f02565b613e41614f41565b6000868152600460205260409020600086815260209190915260409020604051604080820190529081600082613e75614ee6565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff6101009290920a9004168152602001601b82613eab614ee6565b64ffffffffff6101009290920a9004169052509050613ee98682517affffffffffffffffffffffffffffffffffffffffffffffffffffff16876148fb565b816020015190945064ffffffffff1692506117bb915050565b509250929050565b600080613f15614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a613f5161510a565b73ffffffffffffffffffffffffffffffffffffffff1614613fa95760405162461bcd60e51b815260040180806020018281038252602f815260200180615342602f9139604001915050604051809103906121a7614e7b565b565b60006132d78383670de0b6b3a7640000614ad7565b60006132d78383670de0b6b3a7640000614b14565b6000805b8280613fe3614ee6565b90508110156140e95783838281613ff8614ee6565b811061400057fe5b90600052602060002001614012614ee6565b14156140e157828181614023614ee6565b811061402b57fe5b90600052602060002001600090614040614f58565b5050826001848061404f614ee6565b9050038161405b614ee6565b811061406357fe5b90600052602060002001614075614ee6565b838281614080614ee6565b811061408857fe5b90600052602060002001819061409c614f58565b50505082806140a9614ee6565b906140d6907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830161525c565b506001915050610f52565b600101613fd9565b5060009392505050565b60008181526006602052806040812060009061410d614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416905080156141e4578073ffffffffffffffffffffffffffffffffffffffff1663668a0f026040518163ffffffff1660e01b81526004016020604051808303818680614175614fa6565b15801561418a57600080614187614e7b565b50505b505a614194614ff2565b50505050501580156141b3573d6000803e3d60006141b0614e7b565b50505b505050506040513d60208110156141d2576000806141cf614e7b565b50505b8101908080519450610ea89350505050565b6000838152600b602052604090206141fa614ee6565b915050610ea8565b6000600561420e614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a61424a61510a565b73ffffffffffffffffffffffffffffffffffffffff1614613fa95760405162461bcd60e51b815260040180806020018281038252602781526020018061531b60279139604001915050604051809103906121a7614e7b565b60008060006142b08661257d565b9150838614156142c45750839150806124c9565b6142cd8461257d565b905080156124c9576142e98161123b878563ffffffff613fab16565b925093509350939050565b60606001604051908082528060200260200182016040528015614321578160200160208202803883390190505b5090507f466c657869626c6553746f7261676500000000000000000000000000000000008160008151811061435257fe5b60200260200101818152505090565b60608151835101604051908082528060200260200182016040528015614391578160200160208202803883390190505b50905060005b83518110156143d3578381815181106143ac57fe5b60200260200101518282815181106143c057fe5b6020908102919091010152600101614397565b5060005b8251811015614416578281815181106143ec57fe5b602002602001015182828651018151811061440357fe5b60209081029190910101526001016143d7565b5092915050565b60006144276150dd565b600083815260096020526040902060405160a0810160405290818161444a614ee6565b81526020016001820161445b614ee6565b81526020016002820161446c614ee6565b815260200160006003830161447f614ee6565b60ff6101009290920a900416151581526020016001600383016144a0614ee6565b60ff6101009290920a900416151590525090506060810151806132d7575080608001519392505050565b6000826144d957506000610f52565b828202828482816144e657fe5b04146132d75760405162461bcd60e51b81526004018080602001828103825260218152602001806153716021913960400191505060405180910390614529614e7b565b50509392505050565b60006110de7f45786368616e6765720000000000000000000000000000000000000000000000614b46565b600082518451146145a85760405162461bcd60e51b815260040180806020018281038252603881526020018061539260389139604001915050604051809103906145a5614e7b565b50505b6102585a6145b4615216565b0182106146105760405162461bcd60e51b815260206004820152601f60248201527f54696d6520697320746f6f2066617220696e746f20746865206675747572650060448201526064016040518091039061460d614e7b565b50505b60005b845181101561473257600085828151811061462a57fe5b6020026020010151905084828151811061464057fe5b602002602001015161468c5760405162461bcd60e51b81526004018080602001828103825260398152602001806154516039913960400191505060405180910390614689614e7b565b50505b807f735553440000000000000000000000000000000000000000000000000000000014156146f45760405162461bcd60e51b81526004018080602001828103825260318152602001806152ea60319139604001915050604051809103906146f1614e7b565b50505b6146fd816132de565b84101561470a575061472a565b6147288186848151811061471a57fe5b602002602001015186614c60565b505b600101614613565b507f1bc0fc8997efa076f59b5ef02c315bc5390f7a6d24d661ce12128c01a3b0ba578484604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561479a578082015183820152602001614782565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156147d95780820151838201526020016147c1565b5050505090500194505050505060405180910390a15060019392505050565b60006110de7f466c657869626c6553746f726167650000000000000000000000000000000000614b46565b6000808212156148825760405162461bcd60e51b815260206004820152601b60248201527f4e656761746976652072617465206e6f7420737570706f72746564000000000060448201526064016040518091039061487f614e7b565b50505b600083815260076020526040812060009061489b614ee6565b906101000a900460ff1660ff1611156118e557600083815260076020526148de6012604083206000906148cc614ee6565b906101000a900460ff1660ff16614da4565b600a0a90506148f3838263ffffffff6144ca16565b915050610f52565b60006149056150dd565b600085815260096020526040902060405160a08101604052908181614928614ee6565b815260200160018201614939614ee6565b81526020016002820161494a614ee6565b815260200160006003830161495d614ee6565b60ff6101009290920a9004161515815260200160016003830161497e614ee6565b60ff6101009290920a900416151590525090508051158061499d575083155b156149ab57839150506132d7565b6000858152600c602052849250604081206149c4614ee6565b90508084101580156149d7575081606001515b156149e85781602001519250614529565b8084101580156149f9575081608001515b15614a0a5781604001519250614529565b6000614a1f600284519063ffffffff6144ca16565b9050858111614a315760009350614a44565b614a41818763ffffffff614da416565b93505b82602001518410614a5b5782602001519350614a6e565b82604001518411614a6e57826040015193505b5050509392505050565b6000828201838110156132d75760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015260640160405180910390614529614e7b565b600080600a8304614aee868663ffffffff6144ca16565b81614af557fe5b0490506005600a825b0610614b0857600a015b600a9004949350505050565b600080614b3a84614b2e87600a870263ffffffff6144ca16565b9063ffffffff614e0916565b90506005600a82614afe565b600081815260036020528060408120600090614b60614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a9004169050801515836040517f4d697373696e6720616464726573733a2000000000000000000000000000000060208201526031810191909152605101604051602081830303815290604052906144165760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614c16578082015183820152602001614bfe565b50505050905090810190601f168015614c435780820380516001836020036101000a031916815260200191505b509250505060405180910390614c57614e7b565b50505092915050565b6000838152600b60205260409020600081614c79614ee6565b91600183019150614c88614f58565b505050604051604080820181527affffffffffffffffffffffffffffffffffffffffffffffffffffff8416825264ffffffffff831660208084019190915260008681526004909152206000858152600b60205260408120614ce7614ee6565b8152602001908152602001600020815181600181614d03614ee6565b817affffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837affffffffffffffffffffffffffffffffffffffffffffffffffffff16021790614d4d614f58565b5050506020820151817b0100000000000000000000000000000000000000000000000000000081614d7c614ee6565b8164ffffffffff021916908364ffffffffff16021790614d9a614f58565b5050505050505050565b600082821115614e035760405162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015260640160405180910390614e00614e7b565b50505b50900390565b6000808211614e675760405162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015260640160405180910390614e64614e7b565b50505b6000828481614e7257fe5b04949350505050565b632a2a7adb598160e01b8152600481016020815285602082015260005b86811015614eb3578086015182820160400152602001614e98565b506020828760640184336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52505050565b6303daa959598160e01b8152836004820152602081602483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c528051935060005b60408110156116cc57600082820152602001614f2a565b604051604080820190526000808252602082015290565b6322bd64c0598160e01b8152836004820152846024820152600081604483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52600081526020614f2a565b638435035b598160e01b8152836004820152602081602483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c5280516000825293506020614f2a565b638540661f598160e01b8152615023565b8080831115610f52575090919050565b8080831015610f52575090919050565b836004820152846024820152606060448201528660648201526084810160005b8881101561505b578088015182820152602001615043565b506060828960a40184336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52815160408301513d6000853e8b8b82606087013350600060045af150596150b08d3d615013565b8c016150bc8187615003565b5b828110156150d157600081526020016150bd565b50929c50505050505050565b60405160a08101604090815260008083526020830181905290820181905260608201819052608082015290565b6373509064598160e01b8152602081600483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c5280516000825293506020614f2a565b6385979f76598160e01b8152836004820152846024820152606060448201528760648201526084810160005b8981101561519457808901518282015260200161517c565b506060828a60a40184336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52815160408301513d6000853e8c8c82606087013350600060045af150596151e98e3d615013565b8d016151f58187615003565b5b8281101561520a57600081526020016151f6565b50929d50505050505050565b63bdbf8c36598160e01b8152602081600483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c5280516000825293506020614f2a565b81615265614ee6565b818361526f614f58565b5050818111156116cc57818360005260206000206116cc92810191016110e191905b808211156152b057600080826152a5614f58565b505050600101615291565b509056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e65727368697052617465206f6620735553442063616e6e6f7420626520757064617465642c206974277320616c7761797320554e49542e4f6e6c7920746865206f7261636c652063616e20706572666f726d207468697320616374696f6e4f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743757272656e6379206b6579206172726179206c656e677468206d757374206d61746368207261746573206172726179206c656e6774682e6c6f7765724c696d6974206d7573742062652062656c6f772074686520656e747279506f696e7475707065724c696d6974206d757374206265206c657373207468616e20646f75626c6520656e747279506f696e7441676772656761746f7220646563696d616c732073686f756c64206265206c6f776572206f7220657175616c20746f2031385a65726f206973206e6f7420612076616c696420726174652c20706c656173652063616c6c2064656c6574655261746520696e73746561642e75707065724c696d6974206d7573742062652061626f76652074686520656e747279506f696e74"; // A fallback function that allows us to choose between deploying two different initCodes @@ -16,7 +17,6 @@ contract Helper_SimpleOvmDeployer { { bytes memory prefix = hex'600D380380600D6000396000f3'; bytes memory initCode; - console.log("selection", selection); if(selection == 0) { // the resulting deployed bytecode is 0x00 // do concat to be clear @@ -27,6 +27,6 @@ contract Helper_SimpleOvmDeployer { } address addr = Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), initCode); - console.log("deployed address %s", addr); + // console.log("deployed address %s", addr); } } From b1ca4aaef8cadd2ae096adea59cdd1bc91be5f10 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 15:50:47 -0500 Subject: [PATCH 33/39] update benchmarks --- test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 77520cb5d..bcfa3eaa7 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -233,7 +233,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 581_062 + const benchmark: number = 583_841 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, @@ -253,7 +253,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 414_398 + const benchmark: number = 417_183 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, From 4fae9f63778c184fc9448e20e204f7d14e3b7972 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 16:18:09 -0500 Subject: [PATCH 34/39] fix pre-existing EM tests --- .../optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol | 3 --- contracts/test-helpers/Helper_SimpleOvmDeployer.sol | 7 +++++-- .../OVM/execution/OVM_ExecutionManager.gas-spec.ts | 6 +++--- .../execution/OVM_ExecutionManager/context-opcodes.spec.ts | 2 +- .../execution/OVM_ExecutionManager/nuisance-gas.spec.ts | 2 +- .../OVM/execution/OVM_ExecutionManager/ovmCALL.spec.ts | 2 +- .../OVM/execution/OVM_ExecutionManager/ovmCREATE.spec.ts | 1 - .../execution/OVM_ExecutionManager/ovmCREATEEOA.spec.ts | 2 +- .../execution/OVM_ExecutionManager/ovmDELEGATECALL.spec.ts | 2 +- .../OVM/execution/OVM_ExecutionManager/ovmREVERT.spec.ts | 2 +- .../OVM/execution/OVM_ExecutionManager/ovmSLOAD.spec.ts | 1 - .../execution/OVM_ExecutionManager/ovmSTATICCALL.spec.ts | 2 +- .../OVM/execution/OVM_ExecutionManager/run.spec.ts | 2 +- 13 files changed, 16 insertions(+), 18 deletions(-) diff --git a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol index 76c8464a6..099434ed5 100644 --- a/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol +++ b/contracts/optimistic-ethereum/OVM/execution/OVM_SafetyCache.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity >0.5.0 <0.8.0; -import "hardhat/console.sol"; - /* Library Imports */ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; @@ -72,7 +70,6 @@ contract OVM_SafetyCache is iOVM_SafetyCache, Lib_AddressResolver { bool ) { bytes32 codehash = keccak256(abi.encode(_code)); - console.logBytes32(codehash); if(isSafeCodehash[codehash] == true) { return true; } diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol index b37646de6..b0d9cdf12 100644 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -8,8 +8,11 @@ import "hardhat/console.sol"; contract Helper_SimpleOvmDeployer { - // bytecode from "ExchangeRates.sol" as used by Synthetix - bytes constant largeBytecode = hex"608060405234801561001957600080610016614e7b565b50505b506004361061031d5760003560e01c8063654a60ac116101b0578063935f4abd116100f7578063c2c8a676116100a0578063ce8480ea1161007a578063ce8480ea14610e1a578063de02795e14610e40578063fdadbc7e14610e665761031d565b8063c2c8a67614610c70578063c8e5bbd514610d04578063c8e6f39514610df45761031d565b8063b199c764116100d1578063b199c76414610aeb578063b295ad3414610b33578063bfa005ce14610b6f5761031d565b8063935f4abd14610a79578063ac82f60814610a9f578063af3aea8614610ac55761031d565b80637adbf973116101595780638295016a116101335780638295016a14610a13578063899ffef414610a695780638da5cb5b14610a715761031d565b80637adbf973146109a95780637dc0d1d0146109e55780637f6e9d15146109ed5761031d565b8063741853601161018a578063741853601461097357806379ba50971461097b5780637a018a1e146109835761031d565b8063654a60ac146108c25780637103353e146108f4578063728dec291461091a5761031d565b80632af64bd3116102745780633f0e084f1161021d5780634c36b837116101f75780634c36b8371461088c5780634f72def61461089457806353a47bb7146108ba5761031d565b80633f0e084f146107e65780634308a94f1461082857806345938849146108665761031d565b80632ea913d41161024e5780632ea913d4146107745780633375fcd11461079a57806338aa1b99146107c05761031d565b80632af64bd3146106815780632bed9e0c146106895780632d7371e1146106af5761031d565b80630ee4951b116102d65780632528f0fe116102b05780632528f0fe146105e1578063266da16b146106075780632678df96146106455761031d565b80630ee4951b14610551578063109e46a21461056b5780631627540c146105a35761031d565b806305a046e51161030757806305a046e5146103965780630a7d36d11461047d5780630c71cd23146105115761031d565b80629919c01461032b57806304f3bcec14610365575b600080610328614e7b565b50505b6103516004803603602081101561034a57600080610347614e7b565b50505b5035610e92565b604051901515815260200160405180910390f35b61036d610ead565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61042a600480360360208110156103b5576000806103b2614e7b565b50505b8101906020810181356401000000008111156103d9576000806103d6614e7b565b50505b8201836020820111156103f4576000806103f1614e7b565b50505b8035906020019184602083028401116401000000008311171561041f5760008061041c614e7b565b50505b509092509050610ed9565b60405160208082528190810183818151815260200191508051906020019060200280838360005b83811015610469578082015183820152602001610451565b505050509050019250505060405180910390f35b6103516004803603602081101561049c57600080610499614e7b565b50505b8101906020810181356401000000008111156104c0576000806104bd614e7b565b50505b8201836020820111156104db576000806104d8614e7b565b50505b8035906020019184602083028401116401000000008311171561050657600080610503614e7b565b50505b509092509050610f58565b610537600480360360208110156105305760008061052d614e7b565b50505b503561100b565b604051918252151560208201526040908101905180910390f35b6105596110d4565b60405190815260200160405180910390f35b6105596004803603608081101561058a57600080610587614e7b565b50505b50803590602081013590604081013590606001356110e4565b6105df600480360360208110156105c2576000806105bf614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff16611127565b005b61035160048036036020811015610600576000806105fd614e7b565b50505b50356111c8565b610559600480360360a081101561062657600080610623614e7b565b50505b50803590602081013590604081013590606081013590608001356111e8565b61042a6004803603602081101561066457600080610661614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff16611255565b61035161136e565b6105df600480360360208110156106a8576000806106a5614e7b565b50505b5035611563565b6106db600480360360408110156106ce576000806106cb614e7b565b50505b50803590602001356116d1565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561071f578082015183820152602001610707565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561075e578082015183820152602001610746565b5050505090500194505050505060405180910390f35b6105596004803603602081101561079357600080610790614e7b565b50505b50356117c2565b610351600480360360208110156107b9576000806107b6614e7b565b50505b50356117ed565b610351600480360360208110156107df576000806107dc614e7b565b50505b50356118eb565b6105df6004803603604081101561080557600080610802614e7b565b50505b508035906020013573ffffffffffffffffffffffffffffffffffffffff166118f9565b61084e6004803603602081101561084757600080610844614e7b565b50505b5035611c94565b60405191825260208201526040908101905180910390f35b6105df6004803603602081101561088557600080610882614e7b565b50505b5035611ce1565b61036d611e78565b610559600480360360208110156108b3576000806108b0614e7b565b50505b5035611e82565b61036d611e8e565b610559600480360360608110156108e1576000806108de614e7b565b50505b5080359060208101359060400135611e9a565b61036d6004803603602081101561091357600080610910614e7b565b50505b5035611eb2565b6109406004803603602081101561093957600080610936614e7b565b50505b5035611ecc565b604051948552602085019390935260408085019290925215156060840152901515608083015260a0909101905180910390f35b6105df611f37565b6105df6121ab565b610559600480360360208110156109a25760008061099f614e7b565b50505b50356123b8565b6105df600480360360208110156109c8576000806109c5614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff166123c3565b61036d61248e565b61055960048036036020811015610a0c57600080610a09614e7b565b50505b503561249a565b610a4560048036036060811015610a3257600080610a2f614e7b565b50505b50803590602081013590604001356124b2565b60405180848152602001838152602001828152602001935050505060405180910390f35b61042a6124d2565b61036d61255a565b61055960048036036020811015610a9857600080610a95614e7b565b50505b5035612565565b61055960048036036020811015610abe57600080610abb614e7b565b50505b503561257d565b61035160048036036020811015610ae457600080610ae1614e7b565b50505b50356125ac565b6105df600480360360c0811015610b0a57600080610b07614e7b565b50505b50803590602081013590604081013590606081013590608081013515159060a0013515156125b7565b610b5960048036036020811015610b5257600080610b4f614e7b565b50505b5035612aaf565b60405160ff909116815260200160405180910390f35b61035160048036036060811015610b8e57600080610b8b614e7b565b50505b810190602081018135640100000000811115610bb257600080610baf614e7b565b50505b820183602082011115610bcd57600080610bca614e7b565b50505b80359060200191846020830284011164010000000083111715610bf857600080610bf5614e7b565b50505b919390929091602081019035640100000000811115610c1f57600080610c1c614e7b565b50505b820183602082011115610c3a57600080610c37614e7b565b50505b80359060200191846020830284011164010000000083111715610c6557600080610c62614e7b565b50505b919350915035612ad6565b61042a60048036036020811015610c8f57600080610c8c614e7b565b50505b810190602081018135640100000000811115610cb357600080610cb0614e7b565b50505b820183602082011115610cce57600080610ccb614e7b565b50505b80359060200191846020830284011164010000000083111715610cf957600080610cf6614e7b565b50505b509092509050612b5d565b610d9860048036036020811015610d2357600080610d20614e7b565b50505b810190602081018135640100000000811115610d4757600080610d44614e7b565b50505b820183602082011115610d6257600080610d5f614e7b565b50505b80359060200191846020830284011164010000000083111715610d8d57600080610d8a614e7b565b50505b509092509050612bd2565b604051811515602082015260408082528190810184818151815260200191508051906020019060200280838360005b83811015610ddf578082015183820152602001610dc7565b50505050905001935050505060405180910390f35b6105df60048036036020811015610e1357600080610e10614e7b565b50505b5035612d40565b61055960048036036020811015610e3957600080610e36614e7b565b50505b5035612ea3565b6105df60048036036020811015610e5f57600080610e5c614e7b565b50505b5035612eae565b61084e60048036036040811015610e8557600080610e82614e7b565b50505b508035906020013561315a565b6000610ea582610ea0613172565b613293565b90505b919050565b60006002610eb9614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60608082604051908082528060200260200182016040528015610f06578160200160208202803883390190505b50905060005b83811015610f4e57610f2f858583818110610f2357fe5b905060200201356132de565b828281518110610f3b57fe5b6020908102919091010152600101610f0c565b5090505b92915050565b600080610f63613172565b90506060610fa38585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132fa92505050565b905060005b84811015610fff57818181518110610fbc57fe5b602002602001015180610fe65750610fe6868683818110610fd957fe5b9050602002013584613293565b15610ff75760019350505050610f52565b600101610fa8565b50600095945050505050565b600080611016614f41565b61101f846135e4565b9050837f735553440000000000000000000000000000000000000000000000000000000014156110755780517affffffffffffffffffffffffffffffffffffffffffffffffffffff169250600091506110cf9050565b8051611093611082613172565b836020015164ffffffffff16613985565b806110aa57506110aa856110a56139a8565b613a5e565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff90911693509150505b915091565b60006110de613172565b90505b90565b600083815b6110f68783600101613be4565b915050801580611107575083850181115b156111145750905061111f565b6001909101906110e9565b949350505050565b61112f613f0a565b806001808061113c614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790611178614f58565b5050507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce228160405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b60006111d682610ea0613172565b80610ea55750610ea5826110a56139a8565b6000838614156111f957508361124c565b60006112058785613be4565b50905060006112148685613be4565b509050806112275760009250505061124c565b6112478161123b898563ffffffff613fab16565b9063ffffffff613fc016565b925050505b95945050505050565b60606000600880611264614ee6565b905060405190808252806020026020018201604052801561128f578160200160208202803883390190505b50915060005b6008806112a0614ee6565b9050811015611367576000600882816112b7614ee6565b81106112bf57fe5b906000526020600020016112d1614ee6565b6000818152600660205290915073ffffffffffffffffffffffffffffffffffffffff86169060409020600090611305614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561135e578084848060010195508151811061135157fe5b6020026020010181815250505b50600101611295565b5050919050565b6000606061137a6124d2565b905060005b815181101561155a57600082828151811061139657fe5b602002602001015160008181526003602052909150604090206000906113ba614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416600060026113e5614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166321f8a721836040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815260048101919091526024016020604051808303818680611468614fa6565b15801561147d5760008061147a614e7b565b50505b505a611487614ff2565b50505050501580156114a6573d6000803e3d60006114a3614e7b565b50505b505050506040513d60208110156114c5576000806114c2614e7b565b50505b81019080805173ffffffffffffffffffffffffffffffffffffffff169390931415925082915061154090505750600081815260036020526040812060009061150b614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b1561155157600093505050506110e1565b5060010161137f565b50600191505090565b61156b613f0a565b6000818152600660205260408120600090611584614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a9004169050806115ff5760405162461bcd60e51b815260206004820152601c60248201527f4e6f2061676772656761746f722065786973747320666f72206b6579000000006044820152606401604051809103906115fc614e7b565b50505b6000828152600660205260409020600181611618614ee6565b9073ffffffffffffffffffffffffffffffffffffffff0219169061163a614f58565b50506000828152600760205260409020600181611655614ee6565b9060ff02191690611664614f58565b50506000611673836008613fd5565b905080156116cc577fec70e890fc7db7de4059b114c9093a1f41283d18ffcfbcac45566feea4d4f777838360405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a15b505050565b606080826040519080825280602002602001820160405280156116fe578160200160208202803883390190505b5091508260405190808252806020026020018201604052801561172b578160200160208202803883390190505b5090506000611739856140f3565b905060005b848110156117b8576117508683613be4565b85838151811061175c57fe5b6020026020010185848151811061176f57fe5b6020908102919091010191909152528161178b57506117bb9050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019060010161173e565b50505b9250929050565b600a81816117ce614ee6565b81106117d657fe5b9060005260206000200190506117ea614ee6565b81565b60006117f76150dd565b600083815260096020526040902060405160a0810160405290818161181a614ee6565b81526020016001820161182b614ee6565b81526020016002820161183c614ee6565b815260200160006003830161184f614ee6565b60ff6101009290920a90041615158152602001600160038301611870614ee6565b60ff6101009290920a9004161515905250905080511580611892575080606001515b8061189e575080608001515b156118ad576000915050610ea8565b60006118b88461257d565b90506000811180156118dc57508160200151811015806118dc575081604001518111155b92505050610ea8565b50919050565b6000610ea5826110a56139a8565b611901613f0a565b80600073ffffffffffffffffffffffffffffffffffffffff821663668a0f026040518163ffffffff1660e01b81526004016020604051808303818680611945614fa6565b15801561195a57600080611957614e7b565b50505b505a611964614ff2565b5050505050158015611983573d6000803e3d6000611980614e7b565b50505b505050506040513d60208110156119a25760008061199f614e7b565b50505b81019080805193909310159250611a0b9150505760405162461bcd60e51b815260206004820152601b60248201527f476976656e2041676772656761746f7220697320696e76616c69640000000000604482015260640160405180910390611a08614e7b565b50505b60008173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b81526004016020604051808303818680611a4e614fa6565b158015611a6357600080611a60614e7b565b50505b505a611a6d614ff2565b5050505050158015611a8c573d6000803e3d6000611a89614e7b565b50505b505050506040513d6020811015611aab57600080611aa8614e7b565b50505b81019080805193505050601260ff831611159050611b035760405162461bcd60e51b815260040180806020018281038252603281526020018061541f6032913960400191505060405180910390611b00614e7b565b50505b6000848152600660205260408120600090611b1c614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611bb05783600880600181611b64614ee6565b018082611b6f614f58565b50506000928352917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830191506020902091929101611bac614f58565b5050505b60008481526006602052829060409020600181611bcb614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790611c07614f58565b50505060008481526007602052819060409020600181611c25614ee6565b8160ff021916908360ff16021790611c3b614f58565b5050507f0bcae573430f69c5361e5d76534d3f61d2d803958778680cd74be9dc6299bc63848360405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a150505050565b600080611c9f614f41565b611ca8846135e4565b9050805181602001517affffffffffffffffffffffffffffffffffffffffffffffffffffff909116935064ffffffffff16915050915091565b611ce9614202565b6000611cf48261257d565b11611d4e5760405162461bcd60e51b815260206004820152600c60248201527f52617465206973207a65726f0000000000000000000000000000000000000000604482015260640160405180910390611d4b614e7b565b50505b60008181526004602052604090206000828152600b60205260408120611d72614ee6565b8152602001908152602001600020600081600181611d8e614ee6565b907affffffffffffffffffffffffffffffffffffffffffffffffffffff02191690611db7614f58565b508290507b0100000000000000000000000000000000000000000000000000000081611de1614ee6565b9064ffffffffff02191690611df4614f58565b5050506000828152600b6020526040915020600081611e11614ee6565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019150611e3f614f58565b5050507fe69d655565c7ff1353d8eaeea62fb7904fa9696987431ec351be288c865f1ae18160405190815260200160405180910390a150565b60006110de6139a8565b600881816117ce614ee6565b60006001610eb9614ee6565b6000611ea78484846142a2565b509095945050505050565b600660205280600052604060002060009150610eb9614ee6565b6009602052806000526040600020905080611ee5614ee6565b9080600101611ef2614ee6565b9080600201611eff614ee6565b90600060038201611f0e614ee6565b906101000a900460ff169080600301600190611f28614ee6565b906101000a900460ff16905085565b6060611f416124d2565b905060005b81518110156121a7576000828281518110611f5d57fe5b602002602001015190506000806002611f74614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dacb2d0183846040517f5265736f6c766572206d697373696e67207461726765743a2000000000000000602082015260398101919091526059016040516020818303038152906040526040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561204357808201518382015260200161202b565b50505050905090810190601f1680156120705780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818680612089614fa6565b15801561209e5760008061209b614e7b565b50505b505a6120a8614ff2565b50505050501580156120c7573d6000803e3d60006120c4614e7b565b50505b505050506040513d60208110156120e6576000806120e3614e7b565b50505b810190808051600086815260036020529094508493506040925090502060018161210e614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179061214a614f58565b5050507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68828260405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a15050600101611f46565b5050565b600060016121b7614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a6121f361510a565b73ffffffffffffffffffffffffffffffffffffffff161461224e5760405162461bcd60e51b81526004018080602001828103825260358152602001806152b5603591396040019150506040518091039061224b614e7b565b50505b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c60008061227a614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660016000906122a4614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff9283168152911660208201526040908101905180910390a1600060016122fd614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a8161232a614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790612366614f58565b5050506000600160006101000a8161237c614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906116cc614f58565b6000610ea5826140f3565b6123cb613f0a565b8060056001816123d9614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790612415614f58565b5050507f3df77beb5db05fcdd70a30fc8adf3f83f9501b68579455adbd100b81809403946005600090612446614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b60006005610eb9614ee6565b600c60205280600052604060002090506117ea614ee6565b60008060006124c28686866142a2565b9250925092505b93509350939050565b6060806124dd6142f4565b90506060600160405190808252806020026020018201604052801561250c578160200160208202803883390190505b5090507f45786368616e67657200000000000000000000000000000000000000000000008160008151811061253d57fe5b6020026020010181815250506125538282614361565b9250505090565b600080610eb9614ee6565b600b60205280600052604060002090506117ea614ee6565b6000612588826135e4565b517affffffffffffffffffffffffffffffffffffffffffffffffffffff1692915050565b6000610ea58261441d565b6125bf613f0a565b6000831161261c5760405162461bcd60e51b815260206004820152601a60248201527f6c6f7765724c696d6974206d7573742062652061626f76652030000000000000604482015260640160405180910390612619614e7b565b50505b8484116126635760405162461bcd60e51b815260040180806020018281038252602781526020018061548a6027913960400191505060405180910390612660614e7b565b50505b61267485600263ffffffff6144ca16565b84106126ba5760405162461bcd60e51b815260040180806020018281038252602e8152602001806153f1602e9139604001915050604051809103906126b7614e7b565b50505b8483106127015760405162461bcd60e51b81526004018080602001828103825260278152602001806153ca60279139604001915050604051809103906126fe614e7b565b50505b81801561270b5750805b156127655760405162461bcd60e51b815260206004820152601c60248201527f43616e6e6f7420667265657a6520617420626f7468206c696d69747300000000604482015260640160405180910390612762614e7b565b50505b600086815260096020526040812090508061277e614ee6565b6127dd5786600a80600181612791614ee6565b01808261279c614f58565b50506000928352917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301915060209020919291016127d9614f58565b5050505b8580826127e8614f58565b505050848160010181906127fa614f58565b5050508381600201819061280c614f58565b50505082806128185750815b1561291957826003820160018161282d614ee6565b8160ff02191690831515021790612842614f58565b50839150506003820161010081612857614ee6565b8160ff0219169083151502179061286c614f58565b505050600061287a886140f3565b6000898152600c6020529091508190604090208190612897614f58565b5050507ff72828471e37526c68fd812a1fa6eeff993c3f81bd96c0242dc5b3e144145df088856128c757866128c9565b875b835a6128d361510a565b604051938452602084019290925260408084019190915273ffffffffffffffffffffffffffffffffffffffff90911660608301526080909101905180910390a150612989565b60006003820160018161292a614ee6565b8160ff0219169083151502179061293f614f58565b5060009150506003820161010081612955614ee6565b8160ff0219169083151502179061296a614f58565b5050506000878152600c602052604081208190612985614f58565b5050505b60006129948861257d565b90508015612a56576129a4614532565b73ffffffffffffffffffffffffffffffffffffffff1663ce09694089836040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526004810192909252602482015260440160006040518083038160008780612a12614fa6565b158015612a2757600080612a24614e7b565b50505b505a612a31615150565b505050505050158015612a51573d6000803e3d6000612a4e614e7b565b50505b505050505b7f37efb38e92b0f94698f6df0c9070e2f00946862a042ac09e34ae8c547684240a888888886040518085815260200184815260200183815260200182815260200194505050505060405180910390a15050505050505050565b600760205280600052604060002060009150612ac9614ee6565b906101000a900460ff1681565b6000612ae0614202565b612b53868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250889250879150819050602080820201604051908101604052809392919081815260200183836020028082843760009201919091525087925061455d915050565b9695505050505050565b60608082604051908082528060200260200182016040528015612b8a578160200160208202803883390190505b50905060005b83811015610f4e57612bb3858583818110612ba757fe5b9050602002013561257d565b828281518110612bbf57fe5b6020908102919091010152600101612b90565b6060600082604051908082528060200260200182016040528015612c00578160200160208202803883390190505b5091506000612c0d613172565b90506060612c4d8686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132fa92505050565b905060005b85811015612d3657612c62614f41565b612c7d888884818110612c7157fe5b905060200201356135e4565b905080517affffffffffffffffffffffffffffffffffffffffffffffffffffff16868381518110612caa57fe5b60200260200101818152505084158015612cf65750878783818110612ccb57fe5b905060200201357f735553440000000000000000000000000000000000000000000000000000000014155b15612d2d57828281518110612d0757fe5b602002602001015180612d2a5750612d2a84826020015164ffffffffff16613985565b94505b50600101612c52565b5050509250929050565b612d48613f0a565b6000818152600960205260408120612d5e614ee6565b11612db85760405162461bcd60e51b815260206004820152601860248201527f4e6f20696e766572746564207072696365206578697374730000000000000000604482015260640160405180910390612db5614e7b565b50505b600081815260096020526040902060008082612dd2614f58565b505060018201600090612de3614f58565b505060028201600090612df4614f58565b505060038201600181612e05614ee6565b9060ff02191690612e14614f58565b50506003820161010081612e26614ee6565b9060ff02191690612e35614f58565b505050506000612e4682600a613fd5565b905080156121a7577f37efb38e92b0f94698f6df0c9070e2f00946862a042ac09e34ae8c547684240a8260008060006040518085815260200184815260200183815260200182815260200194505050505060405180910390a15050565b6000610ea5826132de565b60008181526009602052604081209050600081612ec9614ee6565b11612f235760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f7420667265657a65206e6f6e2d696e766572736520726174650000604482015260640160405180910390612f20614e7b565b50505b600060038201612f31614ee6565b906101000a900460ff16158015612f5d5750600160038201612f51614ee6565b906101000a900460ff16155b612fb65760405162461bcd60e51b815260206004820152601a60248201527f546865207261746520697320616c72656164792066726f7a656e000000000000604482015260640160405180910390612fb3614e7b565b50505b6000612fc18361257d565b9050600081118015612ff3575081600101612fda614ee6565b81101580612ff3575081600201612fef614ee6565b8111155b156131015781600101613004614ee6565b811460038301600181613015614ee6565b8160ff0219169083151502179061302a614f58565b50505081600201613039614ee6565b8114600383016101008161304b614ee6565b8160ff02191690831515021790613060614f58565b505050600061306e846140f3565b6000858152600c602052909150819060409020819061308b614f58565b5050507ff72828471e37526c68fd812a1fa6eeff993c3f81bd96c0242dc5b3e144145df08483835a6130bb61510a565b604051938452602084019290925260408084019190915273ffffffffffffffffffffffffffffffffffffffff90911660608301526080909101905180910390a1506116cc565b60405162461bcd60e51b815260206004820152601260248201527f526174652077697468696e20626f756e64730000000000000000000000000000604482015260640160405180910390613153614e7b565b5050505050565b6000806131678484613be4565b915091509250929050565b600061317c6147f8565b73ffffffffffffffffffffffffffffffffffffffff166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f726174655374616c65506572696f6400000000000000000000000000000000006040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303818680613228614fa6565b15801561323d5760008061323a614e7b565b50505b505a613247614ff2565b5050505050158015613266573d6000803e3d6000613263614e7b565b50505b505050506040513d602081101561328557600080613282614e7b565b50505b810190808051935050505090565b6000827f735553440000000000000000000000000000000000000000000000000000000014156132c557506000610f52565b6132d7826132d2856132de565b613985565b9392505050565b60006132e9826135e4565b6020015164ffffffffff1692915050565b606060006133066139a8565b905073ffffffffffffffffffffffffffffffffffffffff8116156135b15760608351604051908082528060200260200182016040528015613351578160200160208202803883390190505b50905060005b84518110156133e7576006600086838151811061337057fe5b60200260200101518152602001908152602001600020600090613391614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff168282815181106133ba57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101613357565b508173ffffffffffffffffffffffffffffffffffffffff16637d723cac826040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b8381101561345457808201518382015260200161343c565b50505050905001925050506000604051808303818680613472614fa6565b15801561348757600080613484614e7b565b50505b505a613491614ff2565b50505050501580156134b0573d6000803e3d60006134ad614e7b565b50505b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526020811015613500576000806134fd614e7b565b50505b810190808051604051939291908464010000000082111561352957600080613526614e7b565b50505b90830190602082018581111561354757600080613544614e7b565b50505b825186602082028301116401000000008211171561356d5760008061356a614e7b565b50505b825250602001908051906020019060200280838360005b8381101561359c578082015183820152602001613584565b505050509050016040525050509250506118e5565b82516040519080825280602002602001820160405280156135dc578160200160208202803883390190505b509392505050565b6135ec614f41565b6000828152600660205260408120600090613605614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416905080156138775760606040516024016040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08183030181526040919091527ffeaf968c000000000000000000000000000000000000000000000000000000006020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909117905290506000606073ffffffffffffffffffffffffffffffffffffffff8416836040518082805190602001908083835b6020831061371957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016136dc565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855a613751614ff2565b50505050509150503d80600081146137a3576040513d603f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01681016040523d815291503d6000602084013e6137a8565b606091505b5091509150811561386f576000808060208401845160a08110156137d4576000806137d1614e7b565b50505b810190808051929190602001805192919060200180519291906020018051929190602001805150959850939650909450604093505050505180604001604052806138348b6138228d87614823565b8769ffffffffffffffffffff166148fb565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018264ffffffffff16815250975050505050505050610ea8565b5050506118e5565b6000838152600b6020526040812061388d614ee6565b9050613897614f41565b60008581526004602052604090206000838152602091909152604090206040516040808201905290816000826138cb614ee6565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff6101009290920a9004168152602001601b82613901614ee6565b64ffffffffff6101009290920a9004169052509050604051604080820190528061394a8784517affffffffffffffffffffffffffffffffffffffffffffffffffffff16866148fb565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff168152602001826020015164ffffffffff168152509350505050610ea8565b60005a613990615216565b6139a0838563ffffffff614a7816565b109392505050565b60006139b26147f8565b73ffffffffffffffffffffffffffffffffffffffff16639ee5955a7f53797374656d53657474696e67730000000000000000000000000000000000007f61676772656761746f725761726e696e67466c616773000000000000000000006040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303818680613228614fa6565b6000827f73555344000000000000000000000000000000000000000000000000000000001415613a9057506000610f52565b6000838152600660205260408120600090613aa9614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a9004169050801580613aeb575073ffffffffffffffffffffffffffffffffffffffff8316155b15613afa576000915050610f52565b8273ffffffffffffffffffffffffffffffffffffffff1663357e47fe826040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016020604051808303818680613b76614fa6565b158015613b8b57600080613b88614e7b565b50505b505a613b95614ff2565b5050505050158015613bb4573d6000803e3d6000613bb1614e7b565b50505b505050506040513d6020811015613bd357600080613bd0614e7b565b50505b810190808051979650505050505050565b60008281526006602052808060408120600090613bff614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a90041690508015613e395760608460405160248101919091526044016040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08183030181526040919091527f9a6fc8f5000000000000000000000000000000000000000000000000000000006020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909117905290506000606073ffffffffffffffffffffffffffffffffffffffff8416836040518082805190602001908083835b60208310613d1c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613cdf565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855a613d54614ff2565b50505050509150503d8060008114613da6576040513d603f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01681016040523d815291503d6000602084013e613dab565b606091505b50915091508115613e315760008060208301835160a0811015613dd657600080613dd3614e7b565b50505b8101908080519291906020018051929190602001805192919060200180519291906020018051906020019092919050505050935050925050613e228a613e1c8c85614823565b8b6148fb565b975095506117bb945050505050565b505050613f02565b613e41614f41565b6000868152600460205260409020600086815260209190915260409020604051604080820190529081600082613e75614ee6565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff6101009290920a9004168152602001601b82613eab614ee6565b64ffffffffff6101009290920a9004169052509050613ee98682517affffffffffffffffffffffffffffffffffffffffffffffffffffff16876148fb565b816020015190945064ffffffffff1692506117bb915050565b509250929050565b600080613f15614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a613f5161510a565b73ffffffffffffffffffffffffffffffffffffffff1614613fa95760405162461bcd60e51b815260040180806020018281038252602f815260200180615342602f9139604001915050604051809103906121a7614e7b565b565b60006132d78383670de0b6b3a7640000614ad7565b60006132d78383670de0b6b3a7640000614b14565b6000805b8280613fe3614ee6565b90508110156140e95783838281613ff8614ee6565b811061400057fe5b90600052602060002001614012614ee6565b14156140e157828181614023614ee6565b811061402b57fe5b90600052602060002001600090614040614f58565b5050826001848061404f614ee6565b9050038161405b614ee6565b811061406357fe5b90600052602060002001614075614ee6565b838281614080614ee6565b811061408857fe5b90600052602060002001819061409c614f58565b50505082806140a9614ee6565b906140d6907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830161525c565b506001915050610f52565b600101613fd9565b5060009392505050565b60008181526006602052806040812060009061410d614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416905080156141e4578073ffffffffffffffffffffffffffffffffffffffff1663668a0f026040518163ffffffff1660e01b81526004016020604051808303818680614175614fa6565b15801561418a57600080614187614e7b565b50505b505a614194614ff2565b50505050501580156141b3573d6000803e3d60006141b0614e7b565b50505b505050506040513d60208110156141d2576000806141cf614e7b565b50505b8101908080519450610ea89350505050565b6000838152600b602052604090206141fa614ee6565b915050610ea8565b6000600561420e614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a61424a61510a565b73ffffffffffffffffffffffffffffffffffffffff1614613fa95760405162461bcd60e51b815260040180806020018281038252602781526020018061531b60279139604001915050604051809103906121a7614e7b565b60008060006142b08661257d565b9150838614156142c45750839150806124c9565b6142cd8461257d565b905080156124c9576142e98161123b878563ffffffff613fab16565b925093509350939050565b60606001604051908082528060200260200182016040528015614321578160200160208202803883390190505b5090507f466c657869626c6553746f7261676500000000000000000000000000000000008160008151811061435257fe5b60200260200101818152505090565b60608151835101604051908082528060200260200182016040528015614391578160200160208202803883390190505b50905060005b83518110156143d3578381815181106143ac57fe5b60200260200101518282815181106143c057fe5b6020908102919091010152600101614397565b5060005b8251811015614416578281815181106143ec57fe5b602002602001015182828651018151811061440357fe5b60209081029190910101526001016143d7565b5092915050565b60006144276150dd565b600083815260096020526040902060405160a0810160405290818161444a614ee6565b81526020016001820161445b614ee6565b81526020016002820161446c614ee6565b815260200160006003830161447f614ee6565b60ff6101009290920a900416151581526020016001600383016144a0614ee6565b60ff6101009290920a900416151590525090506060810151806132d7575080608001519392505050565b6000826144d957506000610f52565b828202828482816144e657fe5b04146132d75760405162461bcd60e51b81526004018080602001828103825260218152602001806153716021913960400191505060405180910390614529614e7b565b50509392505050565b60006110de7f45786368616e6765720000000000000000000000000000000000000000000000614b46565b600082518451146145a85760405162461bcd60e51b815260040180806020018281038252603881526020018061539260389139604001915050604051809103906145a5614e7b565b50505b6102585a6145b4615216565b0182106146105760405162461bcd60e51b815260206004820152601f60248201527f54696d6520697320746f6f2066617220696e746f20746865206675747572650060448201526064016040518091039061460d614e7b565b50505b60005b845181101561473257600085828151811061462a57fe5b6020026020010151905084828151811061464057fe5b602002602001015161468c5760405162461bcd60e51b81526004018080602001828103825260398152602001806154516039913960400191505060405180910390614689614e7b565b50505b807f735553440000000000000000000000000000000000000000000000000000000014156146f45760405162461bcd60e51b81526004018080602001828103825260318152602001806152ea60319139604001915050604051809103906146f1614e7b565b50505b6146fd816132de565b84101561470a575061472a565b6147288186848151811061471a57fe5b602002602001015186614c60565b505b600101614613565b507f1bc0fc8997efa076f59b5ef02c315bc5390f7a6d24d661ce12128c01a3b0ba578484604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561479a578082015183820152602001614782565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156147d95780820151838201526020016147c1565b5050505090500194505050505060405180910390a15060019392505050565b60006110de7f466c657869626c6553746f726167650000000000000000000000000000000000614b46565b6000808212156148825760405162461bcd60e51b815260206004820152601b60248201527f4e656761746976652072617465206e6f7420737570706f72746564000000000060448201526064016040518091039061487f614e7b565b50505b600083815260076020526040812060009061489b614ee6565b906101000a900460ff1660ff1611156118e557600083815260076020526148de6012604083206000906148cc614ee6565b906101000a900460ff1660ff16614da4565b600a0a90506148f3838263ffffffff6144ca16565b915050610f52565b60006149056150dd565b600085815260096020526040902060405160a08101604052908181614928614ee6565b815260200160018201614939614ee6565b81526020016002820161494a614ee6565b815260200160006003830161495d614ee6565b60ff6101009290920a9004161515815260200160016003830161497e614ee6565b60ff6101009290920a900416151590525090508051158061499d575083155b156149ab57839150506132d7565b6000858152600c602052849250604081206149c4614ee6565b90508084101580156149d7575081606001515b156149e85781602001519250614529565b8084101580156149f9575081608001515b15614a0a5781604001519250614529565b6000614a1f600284519063ffffffff6144ca16565b9050858111614a315760009350614a44565b614a41818763ffffffff614da416565b93505b82602001518410614a5b5782602001519350614a6e565b82604001518411614a6e57826040015193505b5050509392505050565b6000828201838110156132d75760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015260640160405180910390614529614e7b565b600080600a8304614aee868663ffffffff6144ca16565b81614af557fe5b0490506005600a825b0610614b0857600a015b600a9004949350505050565b600080614b3a84614b2e87600a870263ffffffff6144ca16565b9063ffffffff614e0916565b90506005600a82614afe565b600081815260036020528060408120600090614b60614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a9004169050801515836040517f4d697373696e6720616464726573733a2000000000000000000000000000000060208201526031810191909152605101604051602081830303815290604052906144165760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614c16578082015183820152602001614bfe565b50505050905090810190601f168015614c435780820380516001836020036101000a031916815260200191505b509250505060405180910390614c57614e7b565b50505092915050565b6000838152600b60205260409020600081614c79614ee6565b91600183019150614c88614f58565b505050604051604080820181527affffffffffffffffffffffffffffffffffffffffffffffffffffff8416825264ffffffffff831660208084019190915260008681526004909152206000858152600b60205260408120614ce7614ee6565b8152602001908152602001600020815181600181614d03614ee6565b817affffffffffffffffffffffffffffffffffffffffffffffffffffff02191690837affffffffffffffffffffffffffffffffffffffffffffffffffffff16021790614d4d614f58565b5050506020820151817b0100000000000000000000000000000000000000000000000000000081614d7c614ee6565b8164ffffffffff021916908364ffffffffff16021790614d9a614f58565b5050505050505050565b600082821115614e035760405162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015260640160405180910390614e00614e7b565b50505b50900390565b6000808211614e675760405162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015260640160405180910390614e64614e7b565b50505b6000828481614e7257fe5b04949350505050565b632a2a7adb598160e01b8152600481016020815285602082015260005b86811015614eb3578086015182820160400152602001614e98565b506020828760640184336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52505050565b6303daa959598160e01b8152836004820152602081602483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c528051935060005b60408110156116cc57600082820152602001614f2a565b604051604080820190526000808252602082015290565b6322bd64c0598160e01b8152836004820152846024820152600081604483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52600081526020614f2a565b638435035b598160e01b8152836004820152602081602483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c5280516000825293506020614f2a565b638540661f598160e01b8152615023565b8080831115610f52575090919050565b8080831015610f52575090919050565b836004820152846024820152606060448201528660648201526084810160005b8881101561505b578088015182820152602001615043565b506060828960a40184336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52815160408301513d6000853e8b8b82606087013350600060045af150596150b08d3d615013565b8c016150bc8187615003565b5b828110156150d157600081526020016150bd565b50929c50505050505050565b60405160a08101604090815260008083526020830181905290820181905260608201819052608082015290565b6373509064598160e01b8152602081600483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c5280516000825293506020614f2a565b6385979f76598160e01b8152836004820152846024820152606060448201528760648201526084810160005b8981101561519457808901518282015260200161517c565b506060828a60a40184336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c52815160408301513d6000853e8c8c82606087013350600060045af150596151e98e3d615013565b8d016151f58187615003565b5b8281101561520a57600081526020016151f6565b50929d50505050505050565b63bdbf8c36598160e01b8152602081600483336000905af158601d01573d60011458600c01573d6000803e3d621234565260ea61109c5280516000825293506020614f2a565b81615265614ee6565b818361526f614f58565b5050818111156116cc57818360005260206000206116cc92810191016110e191905b808211156152b057600080826152a5614f58565b505050600101615291565b509056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e65727368697052617465206f6620735553442063616e6e6f7420626520757064617465642c206974277320616c7761797320554e49542e4f6e6c7920746865206f7261636c652063616e20706572666f726d207468697320616374696f6e4f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743757272656e6379206b6579206172726179206c656e677468206d757374206d61746368207261746573206172726179206c656e6774682e6c6f7765724c696d6974206d7573742062652062656c6f772074686520656e747279506f696e7475707065724c696d6974206d757374206265206c657373207468616e20646f75626c6520656e747279506f696e7441676772656761746f7220646563696d616c732073686f756c64206265206c6f776572206f7220657175616c20746f2031385a65726f206973206e6f7420612076616c696420726174652c20706c656173652063616c6c2064656c6574655261746520696e73746561642e75707065724c696d6974206d7573742062652061626f76652074686520656e747279506f696e74"; + // We load the bytcode to deploy as a constant, in order to avoid having to pass it as calldata during testing + // which gets us a more accurate gas benchmark + // slightly reduced bytecode from "ExchangeRates.sol" as used by Synthetix + // the 'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB' is replacing the unlinked library address + bytes constant largeBytecode = hex"60806040523480156200001c576000806200001962000ec0565b50505b506040516200677138038062006771833981810160405260a08110156200004d576000806200004a62000ec0565b50505b810190808051929190602001805192919060200180519291906020018051604051939291908464010000000082111562000091576000806200008e62000ec0565b50505b908301906020820185811115620000b257600080620000af62000ec0565b50505b8251866020820283011164010000000082111715620000db57600080620000d862000ec0565b50505b825250602001908051906020019060200280838360005b838110156200010c578082015183820152602001620000f2565b505050509050016040526020018051604051939291908464010000000082111562000141576000806200013e62000ec0565b50505b90830190602082018581111562000162576000806200015f62000ec0565b50505b82518660208202830111640100000000821117156200018b576000806200018862000ec0565b50505b825250602001908051906020019060200280838360005b83811015620001bc578082015183820152602001620001a2565b5050505090500160405250505082808660006001600160a01b0316816001600160a01b031614156200023f5760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f742062652030000000000000006044820152606401604051809103906200023c62000ec0565b50505b8060006001816200024f62000f2d565b816001600160a01b0302191690836001600160a01b03160217906200027362000f8f565b5050507fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c6000826040516001600160a01b039283168152911660208201526040908101905180910390a150806002600181620002ce62000f2d565b816001600160a01b0302191690836001600160a01b0316021790620002f262000f8f565b50505050508051825114620003445760405162461bcd60e51b815260040180806020018281038252602f8152602001806200667f602f9139604001915050604051809103906200034162000ec0565b50505b8360056001816200035462000f2d565b816001600160a01b0302191690836001600160a01b03160217906200037862000f8f565b50505062000454631cd554d160e21b73BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB63907af6c06040518163ffffffff1660e01b81526004016020604051808303818680620003c862000fde565b158015620003e057600080620003dd62000ec0565b50505b505a620003ec6200102b565b50505050501580156200040e573d6000803e3d60006200040b62000ec0565b50505b505050506040513d602081101562000430576000806200042d62000ec0565b50505b810190808051925050505a6200044562001121565b6001600160e01b036200048016565b6200047482825a6200046562001121565b6001600160e01b036200057e16565b505050505050620011be565b6000838152600b602052604090206000816200049b62000f2d565b91600183019150620004ac62000f8f565b505050604051604080820181526001600160d81b038416825264ffffffffff831660208084019190915260008681526004909152206000858152600b60205260408120620004f962000f2d565b81526020019081526020016000208151816001816200051762000f2d565b816001600160d81b0302191690836001600160d81b03160217906200053b62000f8f565b505050602082015181600160d81b816200055462000f2d565b8164ffffffffff021916908364ffffffffff160217906200057462000f8f565b5050505050505050565b60008251845114620005cd5760405162461bcd60e51b8152600401808060200182810382526038815260200180620067006038913960400191505060405180910390620005ca62000ec0565b50505b6102585a620005db62001121565b0182106200063a5760405162461bcd60e51b815260206004820152601f60248201527f54696d6520697320746f6f2066617220696e746f2074686520667574757265006044820152606401604051809103906200063762000ec0565b50505b60005b8451811015620007685760008582815181106200065657fe5b602002602001015190508482815181106200066d57fe5b6020026020010151620006bd5760405162461bcd60e51b8152600401808060200182810382526039815260200180620067386039913960400191505060405180910390620006ba62000ec0565b50505b80631cd554d160e21b1415620007105760405162461bcd60e51b8152600401808060200182810382526031815260200180620066ae60319139604001915050604051809103906200070d62000ec0565b50505b62000724816001600160e01b036200083316565b8410156200073357506200075f565b6200075d818684815181106200074557fe5b6020026020010151866001600160e01b036200048016565b505b6001016200063d565b507f1bc0fc8997efa076f59b5ef02c315bc5390f7a6d24d661ce12128c01a3b0ba578484604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015620007d2578082015183820152602001620007b8565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101562000813578082015183820152602001620007f9565b5050505090500194505050505060405180910390a15060015b9392505050565b600062000849826001600160e01b036200085c16565b6020015164ffffffffff1690505b919050565b6200086662001168565b60008281526006602052604081206000906200088162000f2d565b6001600160a01b036101009290920a9004169050801562000a5d576060604051602401604051601f19818303018152604091909152633fabe5a360e21b6020820180516001600160e01b031690911790529050600060606001600160a01b038416836040518082805190602001908083835b60208310620009145780518252601f199092019160209182019101620008f3565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855a6200094e6200117f565b50505050509150503d806000811462000984576040513d603f01601f191681016040523d815291503d6000602084013e62000989565b606091505b5091509150811562000a54576000808060208401845160a0811015620009b957600080620009b662000ec0565b50505b8101908080519291906020018051929190602001805192919060200180519291906020018051509598509396509094506040935050505051604080820190528062000a2c8b62000a1381876001600160e01b0362000b4916565b6001600160501b0388166001600160e01b0362000c4a16565b6001600160d81b031681526020018264ffffffffff1681525097505050505050505062000857565b50505062000b43565b6000838152600b6020526040812062000a7562000f2d565b905062000a8162001168565b600085815260046020526040902060008381526020919091526040902060405160408082019052908160008262000ab762000f2d565b6001600160d81b036101009290920a9004168152602001601b8262000adb62000f2d565b64ffffffffff6101009290920a9004169052509050604051604080820190528062000b1b8784516001600160d81b0316866001600160e01b0362000c4a16565b6001600160d81b03168152602001826020015164ffffffffff16815250935050505062000857565b50919050565b60008082121562000bab5760405162461bcd60e51b815260206004820152601b60248201527f4e656761746976652072617465206e6f7420737570706f72746564000000000060448201526064016040518091039062000ba862000ec0565b50505b600083815260076020526040812060009062000bc662000f2d565b906101000a900460ff1660ff16111562000c41576000838152600760205262000c1960126040832060009062000bfb62000f2d565b906101000a900460ff1660ff1662000df760201b62004da41760201c565b600a0a905062000c38818462000e5f60201b620044ca1790919060201c565b91505062000c44565b50805b92915050565b600062000c5662001191565b600085815260096020526040902060405160a0810160405290818162000c7b62000f2d565b81526020016001820162000c8e62000f2d565b81526020016002820162000ca162000f2d565b815260200160006003830162000cb662000f2d565b60ff6101009290920a9004161515815260200160016003830162000cd962000f2d565b60ff6101009290920a900416151590525090508051158062000cf9575083155b1562000d0957839150506200082c565b6000858152600c6020528492506040812062000d2462000f2d565b905080841015801562000d38575081606001515b1562000d4b578160200151925062000dee565b80841015801562000d5d575081608001515b1562000d70578160400151925062000dee565b600062000d8e6002845162000e5f60201b620044ca1790919060201c565b905085811162000da2576000935062000dbf565b62000dbc868262000df760201b62004da41790919060201c565b93505b8260200151841062000dd8578260200151935062000dec565b8260400151841162000dec57826040015193505b505b50509392505050565b60008282111562000e595760405162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f77000060448201526064016040518091039062000e5662000ec0565b50505b50900390565b60008262000e705750600062000c44565b8282028284828162000e7e57fe5b04146200082c5760405162461bcd60e51b8152600401808060200182810382526021815260200180620066df602191396040019150506040518091039062000dee5b632a2a7adb598160e01b8152600481016020815285602082015260005b8681101562000efa57808601518282016040015260200162000edd565b506020828760640184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b505050565b6303daa959598160e01b8152836004820152602081602483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051935060005b604081101562000f8a5760008282015260200162000f71565b505050565b6322bd64c0598160e01b8152836004820152846024820152600081604483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b60008152602062000f71565b638435035b598160e01b8152836004820152602081602483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051600082529350602062000f71565b63ffe73914598160e01b81526200105f565b808083111562000c44575090919050565b808083101562000c44575090919050565b836004820152846024820152606060448201528660648201526084810160005b88811015620010995780880151828201526020016200107f565b506060828960a40184336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b815160408301513d6000853e8b8b82606087013350600060045af15059620010f08d3d6200104e565b8c01620010fe81876200103d565b5b82811015620011155760008152602001620010ff565b50929c50505050505050565b63bdbf8c36598160e01b8152602081600483336000905af158600e01573d6000803e3d6000fd5b3d6001141558600a015760016000f35b8051600082529350602062000f71565b604051604080820190526000808252602082015290565b638540661f598160e01b81526200105f565b60405160a08101604090815260008083526020830181905290820181905260608201819052608082015290565b6154b180620011ce6000396000f3fe608060405234801561001957600080610016614e7b565b50505b506004361061031d5760003560e01c8063654a60ac116101b0578063935f4abd116100f7578063c2c8a676116100a0578063ce8480ea1161007a578063ce8480ea14610e1a578063de02795e14610e40578063fdadbc7e14610e665761031d565b8063c2c8a67614610c70578063c8e5bbd514610d04578063c8e6f39514610df45761031d565b8063b199c764116100d1578063b199c76414610aeb578063b295ad3414610b33578063bfa005ce14610b6f5761031d565b8063935f4abd14610a79578063ac82f60814610a9f578063af3aea8614610ac55761031d565b80637adbf973116101595780638295016a116101335780638295016a14610a13578063899ffef414610a695780638da5cb5b14610a715761031d565b80637adbf973146109a95780637dc0d1d0146109e55780637f6e9d15146109ed5761031d565b8063741853601161018a578063741853601461097357806379ba50971461097b5780637a018a1e146109835761031d565b8063654a60ac146108c25780637103353e146108f4578063728dec291461091a5761031d565b80632af64bd3116102745780633f0e084f1161021d5780634c36b837116101f75780634c36b8371461088c5780634f72def61461089457806353a47bb7146108ba5761031d565b80633f0e084f146107e65780634308a94f1461082857806345938849146108665761031d565b80632ea913d41161024e5780632ea913d4146107745780633375fcd11461079a57806338aa1b99146107c05761031d565b80632af64bd3146106815780632bed9e0c146106895780632d7371e1146106af5761031d565b80630ee4951b116102d65780632528f0fe116102b05780632528f0fe146105e1578063266da16b146106075780632678df96146106455761031d565b80630ee4951b14610551578063109e46a21461056b5780631627540c146105a35761031d565b806305a046e51161030757806305a046e5146103965780630a7d36d11461047d5780630c71cd23146105115761031d565b80629919c01461032b57806304f3bcec14610365575b600080610328614e7b565b50505b6103516004803603602081101561034a57600080610347614e7b565b50505b5035610e92565b604051901515815260200160405180910390f35b61036d610ead565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61042a600480360360208110156103b5576000806103b2614e7b565b50505b8101906020810181356401000000008111156103d9576000806103d6614e7b565b50505b8201836020820111156103f4576000806103f1614e7b565b50505b8035906020019184602083028401116401000000008311171561041f5760008061041c614e7b565b50505b509092509050610ed9565b60405160208082528190810183818151815260200191508051906020019060200280838360005b83811015610469578082015183820152602001610451565b505050509050019250505060405180910390f35b6103516004803603602081101561049c57600080610499614e7b565b50505b8101906020810181356401000000008111156104c0576000806104bd614e7b565b50505b8201836020820111156104db576000806104d8614e7b565b50505b8035906020019184602083028401116401000000008311171561050657600080610503614e7b565b50505b509092509050610f58565b610537600480360360208110156105305760008061052d614e7b565b50505b503561100b565b604051918252151560208201526040908101905180910390f35b6105596110d4565b60405190815260200160405180910390f35b6105596004803603608081101561058a57600080610587614e7b565b50505b50803590602081013590604081013590606001356110e4565b6105df600480360360208110156105c2576000806105bf614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff16611127565b005b61035160048036036020811015610600576000806105fd614e7b565b50505b50356111c8565b610559600480360360a081101561062657600080610623614e7b565b50505b50803590602081013590604081013590606081013590608001356111e8565b61042a6004803603602081101561066457600080610661614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff16611255565b61035161136e565b6105df600480360360208110156106a8576000806106a5614e7b565b50505b5035611563565b6106db600480360360408110156106ce576000806106cb614e7b565b50505b50803590602001356116d1565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b8381101561071f578082015183820152602001610707565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561075e578082015183820152602001610746565b5050505090500194505050505060405180910390f35b6105596004803603602081101561079357600080610790614e7b565b50505b50356117c2565b610351600480360360208110156107b9576000806107b6614e7b565b50505b50356117ed565b610351600480360360208110156107df576000806107dc614e7b565b50505b50356118eb565b6105df6004803603604081101561080557600080610802614e7b565b50505b508035906020013573ffffffffffffffffffffffffffffffffffffffff166118f9565b61084e6004803603602081101561084757600080610844614e7b565b50505b5035611c94565b60405191825260208201526040908101905180910390f35b6105df6004803603602081101561088557600080610882614e7b565b50505b5035611ce1565b61036d611e78565b610559600480360360208110156108b3576000806108b0614e7b565b50505b5035611e82565b61036d611e8e565b610559600480360360608110156108e1576000806108de614e7b565b50505b5080359060208101359060400135611e9a565b61036d6004803603602081101561091357600080610910614e7b565b50505b5035611eb2565b6109406004803603602081101561093957600080610936614e7b565b50505b5035611ecc565b604051948552602085019390935260408085019290925215156060840152901515608083015260a0909101905180910390f35b6105df611f37565b6105df6121ab565b610559600480360360208110156109a25760008061099f614e7b565b50505b50356123b8565b6105df600480360360208110156109c8576000806109c5614e7b565b50505b503573ffffffffffffffffffffffffffffffffffffffff166123c3565b61036d61248e565b61055960048036036020811015610a0c57600080610a09614e7b565b50505b503561249a565b610a4560048036036060811015610a3257600080610a2f614e7b565b50505b50803590602081013590604001356124b2565b60405180848152602001838152602001828152602001935050505060405180910390f35b61042a6124d2565b61036d61255a565b61055960048036036020811015610a9857600080610a95614e7b565b50505b5035612565565b61055960048036036020811015610abe57600080610abb614e7b565b50505b503561257d565b61035160048036036020811015610ae457600080610ae1614e7b565b50505b50356125ac565b6105df600480360360c0811015610b0a57600080610b07614e7b565b50505b50803590602081013590604081013590606081013590608081013515159060a0013515156125b7565b610b5960048036036020811015610b5257600080610b4f614e7b565b50505b5035612aaf565b60405160ff909116815260200160405180910390f35b61035160048036036060811015610b8e57600080610b8b614e7b565b50505b810190602081018135640100000000811115610bb257600080610baf614e7b565b50505b820183602082011115610bcd57600080610bca614e7b565b50505b80359060200191846020830284011164010000000083111715610bf857600080610bf5614e7b565b50505b919390929091602081019035640100000000811115610c1f57600080610c1c614e7b565b50505b820183602082011115610c3a57600080610c37614e7b565b50505b80359060200191846020830284011164010000000083111715610c6557600080610c62614e7b565b50505b919350915035612ad6565b61042a60048036036020811015610c8f57600080610c8c614e7b565b50505b810190602081018135640100000000811115610cb357600080610cb0614e7b565b50505b820183602082011115610cce57600080610ccb614e7b565b50505b80359060200191846020830284011164010000000083111715610cf957600080610cf6614e7b565b50505b509092509050612b5d565b610d9860048036036020811015610d2357600080610d20614e7b565b50505b810190602081018135640100000000811115610d4757600080610d44614e7b565b50505b820183602082011115610d6257600080610d5f614e7b565b50505b80359060200191846020830284011164010000000083111715610d8d57600080610d8a614e7b565b50505b509092509050612bd2565b604051811515602082015260408082528190810184818151815260200191508051906020019060200280838360005b83811015610ddf578082015183820152602001610dc7565b50505050905001935050505060405180910390f35b6105df60048036036020811015610e1357600080610e10614e7b565b50505b5035612d40565b61055960048036036020811015610e3957600080610e36614e7b565b50505b5035612ea3565b6105df60048036036020811015610e5f57600080610e5c614e7b565b50505b5035612eae565b61084e60048036036040811015610e8557600080610e82614e7b565b50505b508035906020013561315a565b6000610ea582610ea0613172565b613293565b90505b919050565b60006002610eb9614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60608082604051908082528060200260200182016040528015610f06578160200160208202803883390190505b50905060005b83811015610f4e57610f2f858583818110610f2357fe5b905060200201356132de565b828281518110610f3b57fe5b6020908102919091010152600101610f0c565b5090505b92915050565b600080610f63613172565b90506060610fa38585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132fa92505050565b905060005b84811015610fff57818181518110610fbc57fe5b602002602001015180610fe65750610fe6868683818110610fd957fe5b9050602002013584613293565b15610ff75760019350505050610f52565b600101610fa8565b50600095945050505050565b600080611016614f41565b61101f846135e4565b9050837f735553440000000000000000000000000000000000000000000000000000000014156110755780517affffffffffffffffffffffffffffffffffffffffffffffffffffff169250600091506110cf9050565b8051611093611082613172565b836020015164ffffffffff16613985565b806110aa57506110aa856110a56139a8565b613a5e565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff90911693509150505b915091565b60006110de613172565b90505b90565b600083815b6110f68783600101613be4565b915050801580611107575083850181115b156111145750905061111f565b6001909101906110e9565b949350505050565b61112f613f0a565b806001808061113c614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790611178614f58565b5050507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce228160405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b60006111d682610ea0613172565b80610ea55750610ea5826110a56139a8565b6000838614156111f957508361124c565b60006112058785613be4565b50905060006112148685613be4565b509050806112275760009250505061124c565b6112478161123b898563ffffffff613fab16565b9063ffffffff613fc016565b925050505b95945050505050565b60606000600880611264614ee6565b905060405190808252806020026020018201604052801561128f578160200160208202803883390190505b50915060005b6008806112a0614ee6565b9050811015611367576000600882816112b7614ee6565b81106112bf57fe5b906000526020600020016112d1614ee6565b6000818152600660205290915073ffffffffffffffffffffffffffffffffffffffff86169060409020600090611305614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561135e578084848060010195508151811061135157fe5b6020026020010181815250505b50600101611295565b5050919050565b6000606061137a6124d2565b905060005b815181101561155a57600082828151811061139657fe5b602002602001015160008181526003602052909150604090206000906113ba614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416600060026113e5614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166321f8a721836040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815260048101919091526024016020604051808303818680611468614fa6565b15801561147d5760008061147a614e7b565b50505b505a611487614ff2565b50505050501580156114a6573d6000803e3d60006114a3614e7b565b50505b505050506040513d60208110156114c5576000806114c2614e7b565b50505b81019080805173ffffffffffffffffffffffffffffffffffffffff169390931415925082915061154090505750600081815260036020526040812060009061150b614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b1561155157600093505050506110e1565b5060010161137f565b50600191505090565b61156b613f0a565b6000818152600660205260408120600090611584614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a9004169050806115ff5760405162461bcd60e51b815260206004820152601c60248201527f4e6f2061676772656761746f722065786973747320666f72206b6579000000006044820152606401604051809103906115fc614e7b565b50505b6000828152600660205260409020600181611618614ee6565b9073ffffffffffffffffffffffffffffffffffffffff0219169061163a614f58565b50506000828152600760205260409020600181611655614ee6565b9060ff02191690611664614f58565b50506000611673836008613fd5565b905080156116cc577fec70e890fc7db7de4059b114c9093a1f41283d18ffcfbcac45566feea4d4f777838360405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a15b505050565b606080826040519080825280602002602001820160405280156116fe578160200160208202803883390190505b5091508260405190808252806020026020018201604052801561172b578160200160208202803883390190505b5090506000611739856140f3565b905060005b848110156117b8576117508683613be4565b85838151811061175c57fe5b6020026020010185848151811061176f57fe5b6020908102919091010191909152528161178b57506117bb9050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091019060010161173e565b50505b9250929050565b600a81816117ce614ee6565b81106117d657fe5b9060005260206000200190506117ea614ee6565b81565b60006117f76150dd565b600083815260096020526040902060405160a0810160405290818161181a614ee6565b81526020016001820161182b614ee6565b81526020016002820161183c614ee6565b815260200160006003830161184f614ee6565b60ff6101009290920a90041615158152602001600160038301611870614ee6565b60ff6101009290920a9004161515905250905080511580611892575080606001515b8061189e575080608001515b156118ad576000915050610ea8565b60006118b88461257d565b90506000811180156118dc57508160200151811015806118dc575081604001518111155b92505050610ea8565b50919050565b6000610ea5826110a56139a8565b611901613f0a565b80600073ffffffffffffffffffffffffffffffffffffffff821663668a0f026040518163ffffffff1660e01b81526004016020604051808303818680611945614fa6565b15801561195a57600080611957614e7b565b50505b505a611964614ff2565b5050505050158015611983573d6000803e3d6000611980614e7b565b50505b505050506040513d60208110156119a25760008061199f614e7b565b50505b81019080805193909310159250611a0b9150505760405162461bcd60e51b815260206004820152601b60248201527f476976656e2041676772656761746f7220697320696e76616c69640000000000604482015260640160405180910390611a08614e7b565b50505b60008173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b81526004016020604051808303818680611a4e614fa6565b158015611a6357600080611a60614e7b565b50505b505a611a6d614ff2565b5050505050158015611a8c573d6000803e3d6000611a89614e7b565b50505b505050506040513d6020811015611aab57600080611aa8614e7b565b50505b81019080805193505050601260ff831611159050611b035760405162461bcd60e51b815260040180806020018281038252603281526020018061541f6032913960400191505060405180910390611b00614e7b565b50505b6000848152600660205260408120600090611b1c614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611bb05783600880600181611b64614ee6565b018082611b6f614f58565b50506000928352917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830191506020902091929101611bac614f58565b5050505b60008481526006602052829060409020600181611bcb614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790611c07614f58565b50505060008481526007602052819060409020600181611c25614ee6565b8160ff021916908360ff16021790611c3b614f58565b5050507f0bcae573430f69c5361e5d76534d3f61d2d803958778680cd74be9dc6299bc63848360405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a150505050565b600080611c9f614f41565b611ca8846135e4565b9050805181602001517affffffffffffffffffffffffffffffffffffffffffffffffffffff909116935064ffffffffff16915050915091565b611ce9614202565b6000611cf48261257d565b11611d4e5760405162461bcd60e51b815260206004820152600c60248201527f52617465206973207a65726f0000000000000000000000000000000000000000604482015260640160405180910390611d4b614e7b565b50505b60008181526004602052604090206000828152600b60205260408120611d72614ee6565b8152602001908152602001600020600081600181611d8e614ee6565b907affffffffffffffffffffffffffffffffffffffffffffffffffffff02191690611db7614f58565b508290507b0100000000000000000000000000000000000000000000000000000081611de1614ee6565b9064ffffffffff02191690611df4614f58565b5050506000828152600b6020526040915020600081611e11614ee6565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019150611e3f614f58565b5050507fe69d655565c7ff1353d8eaeea62fb7904fa9696987431ec351be288c865f1ae18160405190815260200160405180910390a150565b60006110de6139a8565b600881816117ce614ee6565b60006001610eb9614ee6565b6000611ea78484846142a2565b509095945050505050565b600660205280600052604060002060009150610eb9614ee6565b6009602052806000526040600020905080611ee5614ee6565b9080600101611ef2614ee6565b9080600201611eff614ee6565b90600060038201611f0e614ee6565b906101000a900460ff169080600301600190611f28614ee6565b906101000a900460ff16905085565b6060611f416124d2565b905060005b81518110156121a7576000828281518110611f5d57fe5b602002602001015190506000806002611f74614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dacb2d0183846040517f5265736f6c766572206d697373696e67207461726765743a2000000000000000602082015260398101919091526059016040516020818303038152906040526040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561204357808201518382015260200161202b565b50505050905090810190601f1680156120705780820380516001836020036101000a031916815260200191505b5093505050506020604051808303818680612089614fa6565b15801561209e5760008061209b614e7b565b50505b505a6120a8614ff2565b50505050501580156120c7573d6000803e3d60006120c4614e7b565b50505b505050506040513d60208110156120e6576000806120e3614e7b565b50505b810190808051600086815260036020529094508493506040925090502060018161210e614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179061214a614f58565b5050507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa68828260405191825273ffffffffffffffffffffffffffffffffffffffff1660208201526040908101905180910390a15050600101611f46565b5050565b600060016121b7614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a6121f361510a565b73ffffffffffffffffffffffffffffffffffffffff161461224e5760405162461bcd60e51b81526004018080602001828103825260358152602001806152b5603591396040019150506040518091039061224b614e7b565b50505b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c60008061227a614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660016000906122a4614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff9283168152911660208201526040908101905180910390a1600060016122fd614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff166000806101000a8161232a614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790612366614f58565b5050506000600160006101000a8161237c614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217906116cc614f58565b6000610ea5826140f3565b6123cb613f0a565b8060056001816123d9614ee6565b8173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790612415614f58565b5050507f3df77beb5db05fcdd70a30fc8adf3f83f9501b68579455adbd100b81809403946005600090612446614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1660405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b60006005610eb9614ee6565b600c60205280600052604060002090506117ea614ee6565b60008060006124c28686866142a2565b9250925092505b93509350939050565b6060806124dd6142f4565b90506060600160405190808252806020026020018201604052801561250c578160200160208202803883390190505b5090507f45786368616e67657200000000000000000000000000000000000000000000008160008151811061253d57fe5b6020026020010181815250506125538282614361565b9250505090565b600080610eb9614ee6565b600b60205280600052604060002090506117ea614ee6565b6000612588826135e4565b517affffffffffffffffffffffffffffffffffffffffffffffffffffff1692915050565b6000610ea58261441d565b6125bf613f0a565b6000831161261c5760405162461bcd60e51b815260206004820152601a60248201527f6c6f7765724c696d6974206d7573742062652061626f76652030000000000000604482015260640160405180910390612619614e7b565b50505b8484116126635760405162461bcd60e51b815260040180806020018281038252602781526020018061548a6027913960400191505060405180910390612660614e7b565b50505b61267485600263ffffffff6144ca16565b84106126ba5760405162461bcd60e51b815260040180806020018281038252602e8152602001806153f1602e9139604001915050604051809103906126b7614e7b565b50505b8483106127015760405162461bcd60e51b81526004018080602001828103825260278152602001806153ca60279139604001915050604051809103906126fe614e7b565b50505b81801561270b5750805b156127655760405162461bcd60e51b815260206004820152601c60248201527f43616e6e6f7420667265657a6520617420626f7468206c696d69747300000000604482015260640160405180910390612762614e7b565b50505b600086815260096020526040812090508061277e614ee6565b6127dd5786600a80600181612791614ee6565b01808261279c614f58565b50506000928352917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8301915060209020919291016127d9614f58565b5050505b8580826127e8614f58565b505050848160010181906127fa614f58565b5050508381600201819061280c614f58565b50505082806128185750815b1561291957826003820160018161282d614ee6565b8160ff02191690831515021790612842614f58565b50839150506003820161010081612857614ee6565b8160ff0219169083151502179061286c614f58565b505050600061287a886140f3565b6000898152600c6020529091508190604090208190612897614f58565b5050507ff72828471e37526c68fd812a1fa6eeff993c3f81bd96c0242dc5b3e144145df088856128c757866128c9565b875b835a6128d361510a565b604051938452602084019290925260408084019190915273ffffffffffffffffffffffffffffffffffffffff90911660608301526080909101905180910390a150612989565b60006003820160018161292a614ee6565b8160ff0219169083151502179061293f614f58565b5060009150506003820161010081612955614ee6565b8160ff0219169083151502179061296a614f58565b5050506000878152600c602052604081208190612985614f58565b5050505b60006129948861257d565b90508015612a56576129a4614532565b73ffffffffffffffffffffffffffffffffffffffff1663ce09694089836040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526004810192909252602482015260440160006040518083038160008780612a12614fa6565b158015612a2757600080612a24614e7b565b50505b505a612a31615150565b505050505050158015612a51573d6000803e3d6000612a4e614e7b565b50505b505050505b7f37efb38e92b0f94698f6df0c9070e2f00946862a042ac09e34ae8c547684240a888888886040518085815260200184815260200183815260200182815260200194505050505060405180910390a15050505050505050565b600760205280600052604060002060009150612ac9614ee6565b906101000a900460ff1681565b6000612ae0614202565b612b53868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250889250879150819050602080820201604051908101604052809392919081815260200183836020028082843760009201919091525087925061455d915050565b9695505050505050565b60608082604051908082528060200260200182016040528015612b8a578160200160208202803883390190505b50905060005b83811015610f4e57612bb3858583818110612ba757fe5b9050602002013561257d565b828281518110612bbf57fe5b6020908102919091010152600101612b90565b6060600082604051908082528060200260200182016040528015612c00578160200160208202803883390190505b5091506000612c0d613172565b90506060612c4d8686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506132fa92505050565b905060005b85811015612d3657612c62614f41565b612c7d888884818110612c7157fe5b905060200201356135e4565b905080517affffffffffffffffffffffffffffffffffffffffffffffffffffff16868381518110612caa57fe5b60200260200101818152505084158015612cf65750878783818110612ccb57fe5b905060200201357f735553440000000000000000000000000000000000000000000000000000000014155b15612d2d57828281518110612d0757fe5b602002602001015180612d2a5750612d2a84826020015164ffffffffff16613985565b94505b50600101612c52565b5050509250929050565b612d48613f0a565b6000818152600960205260408120612d5e614ee6565b11612db85760405162461bcd60e51b815260206004820152601860248201527f4e6f20696e766572746564207072696365206578697374730000000000000000604482015260640160405180910390612db5614e7b565b50505b600081815260096020526040902060008082612dd2614f58565b505060018201600090612de3614f58565b505060028201600090612df4614f58565b505060038201600181612e05614ee6565b9060ff02191690612e14614f58565b50506003820161010081612e26614ee6565b9060ff02191690612e35614f58565b505050506000612e4682600a613fd5565b905080156121a7577f37efb38e92b0f94698f6df0c9070e2f00946862a042ac09e34ae8c547684240a8260008060006040518085815260200184815260200183815260200182815260200194505050505060405180910390a15050565b6000610ea5826132de565b60008181526009602052604081209050600081612ec9614ee6565b11612f235760405162461bcd60e51b815260206004820152601e60248201527f43616e6e6f7420667265657a65206e6f6e2d696e766572736520726174650000604482015260640160405180910390612f20614e7b565b50505b600060038201612f31614ee6565b906101000a900460ff16158015612f5d5750600160038201612f51614ee6565b906101000a900460ff16155b612fb65760405162461bcd60e51b815260206004820152601a60248201527f546865207261746520697320616c72656164792066726f7a656e000000000000604482015260640160405180910390612fb3614e7b565b50505b6000612fc18361257d565b9050600081118015612ff3575081600101612fda614ee6565b81101580612ff3575081600201612fef614ee6565b8111155b156131015781600101613004614ee6565b811460038301600181613015614ee6565b8160ff0219169083151502179061302a614f58565b50505081600201613039614ee6565b8114600383016101008161304b614ee6565b8160ff02191690831515021790613060614f58565b505050600061306e846140f3565b6000858152600c602052909150819060409020819061308b614f58565b5050507ff72828471e37526c68fd812a1fa6eeff993c3f81bd96c0242dc5b3e144145df08483835a6130bb61510a565b604051938452602084019290925260408084019190915273ffffffffffffffffffffffffffffffffffffffff90911660608301526080909101905180910390a1506116cc565b60405162461bcd60e51b815260206004820152601260248201527f526174652077697468696e20626f756e64730000000000000000000000000000604482015260640160405180910390613153614e7b565b5050505050565b6000806131678484613be4565b915091509250929050565b600061317c6147f8565b73ffffffffffffffffffffffffffffffffffffffff166323257c2b7f53797374656d53657474696e67730000000000000000000000000000000000007f726174655374616c65506572696f6400000000000000000000000000000000006040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303818680613228614fa6565b15801561323d5760008061323a614e7b565b50505b505a613247614ff2565b5050505050158015613266573d6000803e3d6000613263614e7b565b50505b505050506040513d602081101561328557600080613282614e7b565b50505b810190808051935050505090565b6000827f735553440000000000000000000000000000000000000000000000000000000014156132c557506000610f52565b6132d7826132d2856132de565b613985565b9392505050565b60006132e9826135e4565b6020015164ffffffffff1692915050565b606060006133066139a8565b905073ffffffffffffffffffffffffffffffffffffffff8116156135b15760608351604051908082528060200260200182016040528015613351578160200160208202803883390190505b50905060005b84518110156133e7576006600086838151811061337057fe5b60200260200101518152602001908152602001600020600090613391614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff168282815181106133ba57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101613357565b508173ffffffffffffffffffffffffffffffffffffffff16637d723cac826040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b8381101561345457808201518382015260200161343c565b50505050905001925050506000604051808303818680613472614fa6565b15801561348757600080613484614e7b565b50505b505a613491614ff2565b50505050501580156134b0573d6000803e3d60006134ad614e7b565b50505b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526020811015613500576000806134fd614e7b565b50505b810190808051604051939291908464010000000082111561352957600080613526614e7b565b50505b90830190602082018581111561354757600080613544614e7b565b50505b825186602082028301116401000000008211171561356d5760008061356a614e7b565b50505b825250602001908051906020019060200280838360005b8381101561359c578082015183820152602001613584565b505050509050016040525050509250506118e5565b82516040519080825280602002602001820160405280156135dc578160200160208202803883390190505b509392505050565b6135ec614f41565b6000828152600660205260408120600090613605614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416905080156138775760606040516024016040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08183030181526040919091527ffeaf968c000000000000000000000000000000000000000000000000000000006020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909117905290506000606073ffffffffffffffffffffffffffffffffffffffff8416836040518082805190602001908083835b6020831061371957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016136dc565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855a613751614ff2565b50505050509150503d80600081146137a3576040513d603f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01681016040523d815291503d6000602084013e6137a8565b606091505b5091509150811561386f576000808060208401845160a08110156137d4576000806137d1614e7b565b50505b810190808051929190602001805192919060200180519291906020018051929190602001805150959850939650909450604093505050505180604001604052806138348b6138228d87614823565b8769ffffffffffffffffffff166148fb565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018264ffffffffff16815250975050505050505050610ea8565b5050506118e5565b6000838152600b6020526040812061388d614ee6565b9050613897614f41565b60008581526004602052604090206000838152602091909152604090206040516040808201905290816000826138cb614ee6565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff6101009290920a9004168152602001601b82613901614ee6565b64ffffffffff6101009290920a9004169052509050604051604080820190528061394a8784517affffffffffffffffffffffffffffffffffffffffffffffffffffff16866148fb565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff168152602001826020015164ffffffffff168152509350505050610ea8565b60005a613990615216565b6139a0838563ffffffff614a7816565b109392505050565b60006139b26147f8565b73ffffffffffffffffffffffffffffffffffffffff16639ee5955a7f53797374656d53657474696e67730000000000000000000000000000000000007f61676772656761746f725761726e696e67466c616773000000000000000000006040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b168152600481019290925260248201526044016020604051808303818680613228614fa6565b6000827f73555344000000000000000000000000000000000000000000000000000000001415613a9057506000610f52565b6000838152600660205260408120600090613aa9614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a9004169050801580613aeb575073ffffffffffffffffffffffffffffffffffffffff8316155b15613afa576000915050610f52565b8273ffffffffffffffffffffffffffffffffffffffff1663357e47fe826040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016020604051808303818680613b76614fa6565b158015613b8b57600080613b88614e7b565b50505b505a613b95614ff2565b5050505050158015613bb4573d6000803e3d6000613bb1614e7b565b50505b505050506040513d6020811015613bd357600080613bd0614e7b565b50505b810190808051979650505050505050565b60008281526006602052808060408120600090613bff614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a90041690508015613e395760608460405160248101919091526044016040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08183030181526040919091527f9a6fc8f5000000000000000000000000000000000000000000000000000000006020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909117905290506000606073ffffffffffffffffffffffffffffffffffffffff8416836040518082805190602001908083835b60208310613d1c57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613cdf565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855a613d54614ff2565b50505050509150503d8060008114613da6576040513d603f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01681016040523d815291503d6000602084013e613dab565b606091505b50915091508115613e315760008060208301835160a0811015613dd657600080613dd3614e7b565b50505b8101908080519291906020018051929190602001805192919060200180519291906020018051906020019092919050505050935050925050613e228a613e1c8c85614823565b8b6148fb565b975095506117bb945050505050565b505050613f02565b613e41614f41565b6000868152600460205260409020600086815260209190915260409020604051604080820190529081600082613e75614ee6565b7affffffffffffffffffffffffffffffffffffffffffffffffffffff6101009290920a9004168152602001601b82613eab614ee6565b64ffffffffff6101009290920a9004169052509050613ee98682517affffffffffffffffffffffffffffffffffffffffffffffffffffff16876148fb565b816020015190945064ffffffffff1692506117bb915050565b509250929050565b600080613f15614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a613f5161510a565b73ffffffffffffffffffffffffffffffffffffffff1614613fa95760405162461bcd60e51b815260040180806020018281038252602f815260200180615342602f9139604001915050604051809103906121a7614e7b565b565b60006132d78383670de0b6b3a7640000614ad7565b60006132d78383670de0b6b3a7640000614b14565b6000805b8280613fe3614ee6565b90508110156140e95783838281613ff8614ee6565b811061400057fe5b90600052602060002001614012614ee6565b14156140e157828181614023614ee6565b811061402b57fe5b90600052602060002001600090614040614f58565b5050826001848061404f614ee6565b9050038161405b614ee6565b811061406357fe5b90600052602060002001614075614ee6565b838281614080614ee6565b811061408857fe5b90600052602060002001819061409c614f58565b50505082806140a9614ee6565b906140d6907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830161525c565b506001915050610f52565b600101613fd9565b5060009392505050565b60008181526006602052806040812060009061410d614ee6565b73ffffffffffffffffffffffffffffffffffffffff6101009290920a900416905080156141e4578073ffffffffffffffffffffffffffffffffffffffff1663668a0f026040518163ffffffff1660e01b81526004016020604051808303818680614175614fa6565b15801561418a57600080614187614e7b565b50505b505a614194614ff2565b50505050501580156141b3573d6000803e3d60006141b0614e7b565b50505b505050506040513d60208110156141d2576000806141cf614e7b565b50505b8101908080519450610ea89350505050565b6000838152600b602052604090206141fa614ee6565b915050610ea8565b6000600561420e614ee6565b906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff165a61424a61510a565b73ffffffffffffffffffffffffffffffffffffffff1614613fa95760405162461bcd60e51b815260040180806020018281038252602781526020018061531b60279139604001915050604051809103906121a7614e7b565b60008060006142b08661257d565b9150838614156142c45750839150806124c9565b6142cd8461257d565b905080156124c9576142e98161123b878563ffffffff613fab16565b925093509350939050565b60606001604051908082528060200260200182016040528015614321578160200160208202803883390190505b5090507f466c657869626c6553746f7261676500000000000000000000000000000000008160008151811061435257fe5b60200260200101818152505090565b60608151835101604051908082528060200260200182016040528015614391578160200160208202803883390190505b50905060005b83518110156143d3578381815181106143ac57fe5b60200260200101518282815181106143c057fe5b6020908102919091010152600101614397565b5060005b8251811015614416578281815181106143ec57fe5b602002602001015182828651018151811061440357fe5b60209081029190910101526001016143d7565b5092915050565b60006144276150dd565b600083815260096020526040902060405160a0810160405290818161444a614ee6565b81526020016001820161445b614ee6565b81526020016002820161446c614ee6565b815260200160006003830161447f614ee6565b60ff6101009290920a900416151581526020016001600383016144a0614ee6565b60ff6101009290920a900416151590525090506060810151806132d7575080608001519392505050565b6000826144d957506000610f52565b828202828482816144e657fe5b04146132d75760405162461bcd60e51b81526004018080602001828103825260218152602001806153716021913960400191505060405180910390614529614e7b565b50509392505050565b60006110de7f45786368616e6765720000000000000000000000000000000000000000000000614b46565b600082518451146145a85760405162461bcd60e51b815260040180806020018281038252603881526020018061539260389139604001915050604051809103906145a5614e7b565b50505b6102585a6145b4615216565b0182106146105760405162461bcd60e51b815260206004820152601f60248201527f54696d6520697320746f6f2066617220696e746f20746865206675747572650060448201526064016040518091039061460d614e7b565b50505b60005b845181101561473257600085828151811061462a57fe5b6020026020010151905084828151811061464057fe5b602002602001015161468c5760405162461bcd60e51b81526004018080602001828103825260398152602001806154516039913960400191505060405180910390614689614e7b565b50505b807f735553440000000000000000000000000000000000000000000000000000000014156146f45760405162461bcd60e51b81526004018080602001828103825260318152602001806152ea60319139604001915050604051809103906146f1614e7b565b50505b6146fd816132de565b84101561470a575061472a565b6147288186848151811061471a57fe5b602002602001015186614c60565b505b600101614613565b507f1bc0fc8997efa076f59b5ef02c315bc5390f7a6d24d661ce12128c01a3b0ba5784846040518080602001806020018381038352858181518152602001915080519060"; // A fallback function that allows us to choose between deploying two different initCodes function deploy(uint256 selection) diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index bcfa3eaa7..2b715d0f5 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -35,7 +35,7 @@ const QUEUE_ORIGIN = { L1TOL2_QUEUE: 1, } -describe.only('OVM_ExecutionManager Benchmarks', () => { +describe('OVM_ExecutionManager Benchmarks', () => { describe('em.run() benchmark: executing a minimal contract', async () => { let wallet: Signer let Factory__OVM_ExecutionManager: ContractFactory @@ -272,7 +272,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 581_062 + const benchmark: number = 7_046_427 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, @@ -291,7 +291,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 581_062 + const benchmark: number = 5_539_103 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/context-opcodes.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/context-opcodes.spec.ts index bddcd4baa..eae7ef693 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/context-opcodes.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/context-opcodes.spec.ts @@ -29,7 +29,7 @@ const test_contextOpcodes: TestDefinition = { preState: { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', - ovmSafetyChecker: '$OVM_SAFETY_CHECKER', + ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, }, diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts index 2f1fd9f58..6a80bf423 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts @@ -22,7 +22,7 @@ const test_nuisanceGas: TestDefinition = { preState: { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', - ovmSafetyChecker: '$OVM_SAFETY_CHECKER', + ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, }, diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCALL.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCALL.spec.ts index 6ff25e814..6749a3ebd 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCALL.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCALL.spec.ts @@ -18,7 +18,7 @@ const test_ovmCALL: TestDefinition = { preState: { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', - ovmSafetyChecker: '$OVM_SAFETY_CHECKER', + ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, }, diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATE.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATE.spec.ts index e2bc2c3d1..79014851c 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATE.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATE.spec.ts @@ -39,7 +39,6 @@ const test_ovmCREATE: TestDefinition = { preState: { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', - ovmSafetyChecker: '$OVM_SAFETY_CHECKER', ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATEEOA.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATEEOA.spec.ts index 09ad78d59..39f3477e2 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATEEOA.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmCREATEEOA.spec.ts @@ -16,7 +16,7 @@ const test_ovmCREATEEOA: TestDefinition = { preState: { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', - ovmSafetyChecker: '$OVM_SAFETY_CHECKER', + ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, }, diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmDELEGATECALL.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmDELEGATECALL.spec.ts index a6d114c75..c63cd00b1 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmDELEGATECALL.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmDELEGATECALL.spec.ts @@ -16,7 +16,7 @@ const test_ovmDELEGATECALL: TestDefinition = { preState: { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', - ovmSafetyChecker: '$OVM_SAFETY_CHECKER', + ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, }, diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmREVERT.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmREVERT.spec.ts index fb5590c90..90c11425c 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmREVERT.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmREVERT.spec.ts @@ -12,7 +12,7 @@ const test_ovmREVERT: TestDefinition = { preState: { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', - ovmSafetyChecker: '$OVM_SAFETY_CHECKER', + ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, }, diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSLOAD.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSLOAD.spec.ts index bc0628635..6f71af6b4 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSLOAD.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSLOAD.spec.ts @@ -13,7 +13,6 @@ const test_ovmSLOAD: TestDefinition = { preState: { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', - ovmSafetyChecker: '$OVM_SAFETY_CHECKER', ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSTATICCALL.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSTATICCALL.spec.ts index 33b507805..78d1e2939 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSTATICCALL.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/ovmSTATICCALL.spec.ts @@ -15,7 +15,7 @@ const test_ovmSTATICCALL: TestDefinition = { preState: { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', - ovmSafetyChecker: '$OVM_SAFETY_CHECKER', + ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, }, diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager/run.spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager/run.spec.ts index 18cfd8afe..ae4eb260a 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager/run.spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager/run.spec.ts @@ -27,7 +27,7 @@ const test_run: TestDefinition = { preState: { ExecutionManager: { ovmStateManager: '$OVM_STATE_MANAGER', - ovmSafetyChecker: '$OVM_SAFETY_CHECKER', + ovmSafetyCache: '$OVM_SAFETY_CACHE', messageRecord: { nuisanceGasLeft: OVM_TX_GAS_LIMIT, }, From ce61e01c9af2f2340a0449db32a852e31c559993 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 16:59:49 -0500 Subject: [PATCH 35/39] with .only --- contracts/test-helpers/Helper_SimpleOvmDeployer.sol | 2 +- test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol index b0d9cdf12..267e70c17 100644 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -30,6 +30,6 @@ contract Helper_SimpleOvmDeployer { } address addr = Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), initCode); - // console.log("deployed address %s", addr); + console.log("deployed address %s", addr); } } diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 2b715d0f5..180315eac 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -35,7 +35,7 @@ const QUEUE_ORIGIN = { L1TOL2_QUEUE: 1, } -describe('OVM_ExecutionManager Benchmarks', () => { +describe.only('OVM_ExecutionManager Benchmarks', () => { describe('em.run() benchmark: executing a minimal contract', async () => { let wallet: Signer let Factory__OVM_ExecutionManager: ContractFactory From 9ec03a47e265fa97e2982dd252512cc952e8f610 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 17:16:52 -0500 Subject: [PATCH 36/39] lint:fix --- .../OVM_ExecutionManager.gas-spec.ts | 126 ++++++++++-------- test/helpers/test-runner/test-runner.ts | 2 +- 2 files changed, 72 insertions(+), 56 deletions(-) diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 180315eac..3a1c7d120 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -5,10 +5,7 @@ import { deployContractCode } from '../../../helpers/utils' import { BigNumber } from 'ethers' import { ethers } from 'hardhat' import { Contract, ContractFactory, Signer } from 'ethers' -import { - smockit, - MockContract, -} from '@eth-optimism/smock' +import { smockit, MockContract } from '@eth-optimism/smock' /* Internal Imports */ import { @@ -16,7 +13,7 @@ import { NON_ZERO_ADDRESS, NON_NULL_BYTES32, GasMeasurement, - DUMMY_BYTES32 + DUMMY_BYTES32, } from '../../../helpers' const DUMMY_GASMETERCONFIG = { @@ -37,20 +34,20 @@ const QUEUE_ORIGIN = { describe.only('OVM_ExecutionManager Benchmarks', () => { describe('em.run() benchmark: executing a minimal contract', async () => { - let wallet: Signer + let wallet: Signer let Factory__OVM_ExecutionManager: ContractFactory let OVM_ExecutionManager: Contract let MOCK__STATE_MANAGER: MockContract let AddressManager: Contract let targetContractAddress: string let gasMeasurement: GasMeasurement - let DUMMY_TRANSACTION; + let DUMMY_TRANSACTION before(async () => { ;[wallet] = await ethers.getSigners() Factory__OVM_ExecutionManager = await ethers.getContractFactory( 'OVM_ExecutionManager' ) - + DUMMY_TRANSACTION = { timestamp: 111111111111, blockNumber: 20, @@ -68,16 +65,16 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { 10_000_000 ) DUMMY_TRANSACTION.entrypoint = targetContractAddress - + AddressManager = await makeAddressManager() - + // deploy the state manager and mock it for the state transitioner MOCK__STATE_MANAGER = await smockit( await (await ethers.getContractFactory('OVM_StateManager')).deploy( NON_ZERO_ADDRESS ) ) - + // Setup the SM to satisfy all the checks executed during EM.run() MOCK__STATE_MANAGER.smocked.isAuthenticated.will.return.with(true) MOCK__STATE_MANAGER.smocked.getAccountEthAddress.will.return.with( @@ -85,12 +82,12 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { ) MOCK__STATE_MANAGER.smocked.hasAccount.will.return.with(true) MOCK__STATE_MANAGER.smocked.testAndSetAccountLoaded.will.return.with(true) - + await AddressManager.setAddress( 'OVM_StateManagerFactory', MOCK__STATE_MANAGER.address ) - + gasMeasurement = new GasMeasurement() await gasMeasurement.init(wallet) OVM_ExecutionManager = ( @@ -135,16 +132,16 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { AddressManager = await makeAddressManager() // Deploy Safety Checker and register it with the Address Manager - OVM_SafetyChecker = await ( + OVM_SafetyChecker = await ( await ethers.getContractFactory('OVM_SafetyChecker') ).deploy() await AddressManager.setAddress( 'OVM_SafetyChecker', OVM_SafetyChecker.address ) - + // Deploy Safety Cache and register it with the Address Manager - OVM_SafetyCache = await ( + OVM_SafetyCache = await ( await ethers.getContractFactory('OVM_SafetyCache') ).deploy(AddressManager.address) await AddressManager.setAddress( @@ -153,10 +150,12 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { ) // Setup Mock Deployer Whitelist and register it with the Address Manager - MOCK__OVM_DeployerWhitelist = await smockit( + MOCK__OVM_DeployerWhitelist = await smockit( await ethers.getContractFactory('OVM_DeployerWhitelist') ) - MOCK__OVM_DeployerWhitelist.smocked.isDeployerAllowed.will.return.with(true) + MOCK__OVM_DeployerWhitelist.smocked.isDeployerAllowed.will.return.with( + true + ) await AddressManager.setAddress( 'OVM_DeployerWhitelist', MOCK__OVM_DeployerWhitelist.address @@ -170,7 +169,6 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { DUMMY_GASMETERCONFIG, DUMMY_GLOBALCONTEXT ) - // Deploy GasMeasurement utility gasMeasurement = new GasMeasurement() @@ -179,23 +177,20 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { // Setup the State Manger and modify it to allow execution to proceed OVM_StateManager = await ( await ethers.getContractFactory('OVM_StateManager') - ).deploy( - await wallet.getAddress() - ) - + ).deploy(await wallet.getAddress()) + // Setup the SM to satisfy all the checks executed during EM.run() await OVM_StateManager.putAccount( - "0x4200000000000000000000000000000000000002", + '0x4200000000000000000000000000000000000002', { nonce: BigNumber.from(123), balance: BigNumber.from(456), storageRoot: DUMMY_BYTES32[0], codeHash: DUMMY_BYTES32[1], ethAddress: MOCK__OVM_DeployerWhitelist.address, - }, - ); + } + ) await OVM_StateManager.setExecutionManager(OVM_ExecutionManager.address) - // Deploy a simple OVM-safe contract that just deploys another contract Helper_SimpleDeployer = await ( @@ -208,29 +203,32 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { l1TxOrigin: NON_ZERO_ADDRESS, entrypoint: Helper_SimpleDeployer.address, gasLimit: 10_000_000, - data: Helper_SimpleDeployer.interface.encodeFunctionData('deploy(uint256)', [0]) + data: Helper_SimpleDeployer.interface.encodeFunctionData( + 'deploy(uint256)', + [0] + ), } - await OVM_StateManager.putAccount( - Helper_SimpleDeployer.address, - { - nonce: BigNumber.from(123), - balance: BigNumber.from(456), - storageRoot: DUMMY_BYTES32[0], - codeHash: DUMMY_BYTES32[1], - ethAddress: Helper_SimpleDeployer.address, - }, - ) - + await OVM_StateManager.putAccount(Helper_SimpleDeployer.address, { + nonce: BigNumber.from(123), + balance: BigNumber.from(456), + storageRoot: DUMMY_BYTES32[0], + codeHash: DUMMY_BYTES32[1], + ethAddress: Helper_SimpleDeployer.address, + }) }) it('Gas Benchmark: un-cached minimal contract deployment', async () => { // Set destination for first contract deployment await OVM_StateManager.putEmptyAccount( - "0xf7a70a9ed665630eaaf9f7b40b71f01cbf65f73f" + '0xf7a70a9ed665630eaaf9f7b40b71f01cbf65f73f' + ) + const tx = await OVM_ExecutionManager.run( + DUMMY_TRANSACTION, + OVM_StateManager.address ) - const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, OVM_StateManager.address) await tx.wait() - const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed + const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)) + .gasUsed console.log(` calculated gas cost of ${gasCost}`) const benchmark: number = 583_841 @@ -240,17 +238,21 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { 'Gas cost has significantly decreased, consider updating the benchmark to reflect the change' ) }) - + it('Gas Benchmark: cached minimal contract deployment', async () => { // Set destination for second contract deployment await OVM_StateManager.putEmptyAccount( - "0xd236d314fd67606dddb3885f1330cf9bd3c8dbea" + '0xd236d314fd67606dddb3885f1330cf9bd3c8dbea' ) // run the exact same flow as the previous. This time the Safety Cache should recognize the string. - const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, OVM_StateManager.address) + const tx = await OVM_ExecutionManager.run( + DUMMY_TRANSACTION, + OVM_StateManager.address + ) await tx.wait() - const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed + const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)) + .gasUsed console.log(` calculated gas cost of ${gasCost}`) const benchmark: number = 417_183 @@ -262,14 +264,21 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { }) it('Gas Benchmark: un-cached larger contract deployment ', async () => { - DUMMY_TRANSACTION.data = Helper_SimpleDeployer.interface.encodeFunctionData('deploy(uint256)', [1]) + DUMMY_TRANSACTION.data = Helper_SimpleDeployer.interface.encodeFunctionData( + 'deploy(uint256)', + [1] + ) // Set destination for first contract deployment await OVM_StateManager.putEmptyAccount( - "0x2dbd79d558282f50005be8e44c90a2db31042b40" + '0x2dbd79d558282f50005be8e44c90a2db31042b40' + ) + const tx = await OVM_ExecutionManager.run( + DUMMY_TRANSACTION, + OVM_StateManager.address ) - const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, OVM_StateManager.address) await tx.wait() - const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed + const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)) + .gasUsed console.log(` calculated gas cost of ${gasCost}`) const benchmark: number = 7_046_427 @@ -279,16 +288,23 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { 'Gas cost has significantly decreased, consider updating the benchmark to reflect the change' ) }) - + it('Gas Benchmark: cached larger contract deployment ', async () => { - DUMMY_TRANSACTION.data = Helper_SimpleDeployer.interface.encodeFunctionData('deploy(uint256)', [1]) + DUMMY_TRANSACTION.data = Helper_SimpleDeployer.interface.encodeFunctionData( + 'deploy(uint256)', + [1] + ) // Set destination for first contract deployment await OVM_StateManager.putEmptyAccount( - "0x7715813e9ee6baab3cb5ea89edc16fa92d526a74" + '0x7715813e9ee6baab3cb5ea89edc16fa92d526a74' + ) + const tx = await OVM_ExecutionManager.run( + DUMMY_TRANSACTION, + OVM_StateManager.address ) - const tx = await OVM_ExecutionManager.run(DUMMY_TRANSACTION, OVM_StateManager.address) await tx.wait() - const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)).gasUsed + const gasCost = (await ethers.provider.getTransactionReceipt(tx.hash)) + .gasUsed console.log(` calculated gas cost of ${gasCost}`) const benchmark: number = 5_539_103 diff --git a/test/helpers/test-runner/test-runner.ts b/test/helpers/test-runner/test-runner.ts index 45beb1fa4..62a467765 100644 --- a/test/helpers/test-runner/test-runner.ts +++ b/test/helpers/test-runner/test-runner.ts @@ -216,7 +216,7 @@ export class ExecutionManagerTestRunner { MockSafetyCache.smocked.checkAndRegisterSafeBytecode.will.return.with(true) this.contracts.OVM_SafetyCache = MockSafetyCache - + await AddressManager.setAddress( 'OVM_SafetyCache', this.contracts.OVM_SafetyCache.address From 4a60b1908d7af18667047d5c5bb3aca1964fea70 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 20:10:04 -0500 Subject: [PATCH 37/39] Add getCreateAddress function --- .../test-helpers/Helper_SimpleOvmDeployer.sol | 1 - .../OVM_ExecutionManager.gas-spec.ts | 54 +++++++++++++------ 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol index 267e70c17..9eb194d2a 100644 --- a/contracts/test-helpers/Helper_SimpleOvmDeployer.sol +++ b/contracts/test-helpers/Helper_SimpleOvmDeployer.sol @@ -30,6 +30,5 @@ contract Helper_SimpleOvmDeployer { } address addr = Lib_SafeExecutionManagerWrapper.safeCREATE(gasleft(), initCode); - console.log("deployed address %s", addr); } } diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 3a1c7d120..166b7c9da 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -32,7 +32,16 @@ const QUEUE_ORIGIN = { L1TOL2_QUEUE: 1, } -describe.only('OVM_ExecutionManager Benchmarks', () => { +const getCreateAddress = async (stateManager: Contract, creator: string) => { + let creatorNonce = await stateManager.getAccountNonce(creator) + let createAddress = ethers.utils.getContractAddress({ + from: creator, + nonce: creatorNonce, + }) + return createAddress +} + +describe('OVM_ExecutionManager Benchmarks', () => { describe('em.run() benchmark: executing a minimal contract', async () => { let wallet: Signer let Factory__OVM_ExecutionManager: ContractFactory @@ -196,6 +205,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { Helper_SimpleDeployer = await ( await ethers.getContractFactory('Helper_SimpleOvmDeployer') ).deploy() + DUMMY_TRANSACTION = { timestamp: 111111111111, blockNumber: 20, @@ -218,10 +228,13 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { }) it('Gas Benchmark: un-cached minimal contract deployment', async () => { - // Set destination for first contract deployment - await OVM_StateManager.putEmptyAccount( - '0xf7a70a9ed665630eaaf9f7b40b71f01cbf65f73f' + let createAddr = await getCreateAddress( + OVM_StateManager, + Helper_SimpleDeployer.address ) + + // Set destination for first contract deployment + await OVM_StateManager.putEmptyAccount(createAddr) const tx = await OVM_ExecutionManager.run( DUMMY_TRANSACTION, OVM_StateManager.address @@ -231,7 +244,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { .gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 583_841 + const benchmark: number = 581_993 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, @@ -241,9 +254,11 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { it('Gas Benchmark: cached minimal contract deployment', async () => { // Set destination for second contract deployment - await OVM_StateManager.putEmptyAccount( - '0xd236d314fd67606dddb3885f1330cf9bd3c8dbea' + let createAddr = await getCreateAddress( + OVM_StateManager, + Helper_SimpleDeployer.address ) + await OVM_StateManager.putEmptyAccount(createAddr) // run the exact same flow as the previous. This time the Safety Cache should recognize the string. const tx = await OVM_ExecutionManager.run( @@ -255,7 +270,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { .gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 417_183 + const benchmark: number = 415_329 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, @@ -268,10 +283,13 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { 'deploy(uint256)', [1] ) - // Set destination for first contract deployment - await OVM_StateManager.putEmptyAccount( - '0x2dbd79d558282f50005be8e44c90a2db31042b40' + + let createAddr = await getCreateAddress( + OVM_StateManager, + Helper_SimpleDeployer.address ) + // Set destination for first contract deployment + await OVM_StateManager.putEmptyAccount(createAddr) const tx = await OVM_ExecutionManager.run( DUMMY_TRANSACTION, OVM_StateManager.address @@ -281,7 +299,7 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { .gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 7_046_427 + const benchmark: number = 7_044_545 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( benchmark - 1_000, @@ -294,10 +312,12 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { 'deploy(uint256)', [1] ) - // Set destination for first contract deployment - await OVM_StateManager.putEmptyAccount( - '0x7715813e9ee6baab3cb5ea89edc16fa92d526a74' + // Set destination for contract deployment + let createAddr = await getCreateAddress( + OVM_StateManager, + Helper_SimpleDeployer.address ) + await OVM_StateManager.putEmptyAccount(createAddr) const tx = await OVM_ExecutionManager.run( DUMMY_TRANSACTION, OVM_StateManager.address @@ -307,10 +327,10 @@ describe.only('OVM_ExecutionManager Benchmarks', () => { .gasUsed console.log(` calculated gas cost of ${gasCost}`) - const benchmark: number = 5_539_103 + const benchmark: number = 5_537_215 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( - benchmark - 1_000, + benchmark - 1_000, 'Gas cost has significantly decreased, consider updating the benchmark to reflect the change' ) }) From 09fa85453d25ce0db1b2458f209fb7ef8686e64c Mon Sep 17 00:00:00 2001 From: Maurelian Date: Tue, 9 Mar 2021 21:33:28 -0500 Subject: [PATCH 38/39] Lint --- .../execution/OVM_ExecutionManager.gas-spec.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 166b7c9da..97d1bca48 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -2,9 +2,8 @@ import { expect } from '../../../setup' import { deployContractCode } from '../../../helpers/utils' /* External Imports */ -import { BigNumber } from 'ethers' import { ethers } from 'hardhat' -import { Contract, ContractFactory, Signer } from 'ethers' +import { BigNumber, Contract, ContractFactory, Signer } from 'ethers' import { smockit, MockContract } from '@eth-optimism/smock' /* Internal Imports */ @@ -33,8 +32,8 @@ const QUEUE_ORIGIN = { } const getCreateAddress = async (stateManager: Contract, creator: string) => { - let creatorNonce = await stateManager.getAccountNonce(creator) - let createAddress = ethers.utils.getContractAddress({ + const creatorNonce = await stateManager.getAccountNonce(creator) + const createAddress = ethers.utils.getContractAddress({ from: creator, nonce: creatorNonce, }) @@ -228,7 +227,7 @@ describe('OVM_ExecutionManager Benchmarks', () => { }) it('Gas Benchmark: un-cached minimal contract deployment', async () => { - let createAddr = await getCreateAddress( + const createAddr = await getCreateAddress( OVM_StateManager, Helper_SimpleDeployer.address ) @@ -254,7 +253,7 @@ describe('OVM_ExecutionManager Benchmarks', () => { it('Gas Benchmark: cached minimal contract deployment', async () => { // Set destination for second contract deployment - let createAddr = await getCreateAddress( + const createAddr = await getCreateAddress( OVM_StateManager, Helper_SimpleDeployer.address ) @@ -284,7 +283,7 @@ describe('OVM_ExecutionManager Benchmarks', () => { [1] ) - let createAddr = await getCreateAddress( + const createAddr = await getCreateAddress( OVM_StateManager, Helper_SimpleDeployer.address ) @@ -313,7 +312,7 @@ describe('OVM_ExecutionManager Benchmarks', () => { [1] ) // Set destination for contract deployment - let createAddr = await getCreateAddress( + const createAddr = await getCreateAddress( OVM_StateManager, Helper_SimpleDeployer.address ) @@ -330,7 +329,7 @@ describe('OVM_ExecutionManager Benchmarks', () => { const benchmark: number = 5_537_215 expect(gasCost).to.be.lte(benchmark) expect(gasCost).to.be.gte( - benchmark - 1_000, + benchmark - 1_000, 'Gas cost has significantly decreased, consider updating the benchmark to reflect the change' ) }) From 46e794a37c5348cc4248b83beab84c6f6e1b18f5 Mon Sep 17 00:00:00 2001 From: Maurelian Date: Wed, 10 Mar 2021 13:21:08 -0500 Subject: [PATCH 39/39] More accurate describe string --- test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts index 97d1bca48..b4f620780 100644 --- a/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts +++ b/test/contracts/OVM/execution/OVM_ExecutionManager.gas-spec.ts @@ -122,7 +122,7 @@ describe('OVM_ExecutionManager Benchmarks', () => { ) }) }) - describe('em.run() benchmark: deploying a minimal contract', async () => { + describe('em.run() benchmark: contract deployment', async () => { let Helper_SimpleDeployer: Contract let wallet: Signer let OVM_SafetyChecker: Contract