# Measurable benefits of EOF We compared EVM bytecode size, gas usage and execution time of popular mainnet contracts (UniswapV3 and ENS DNSRegistrar). We used [Solidity compiler branch](https://github.com/ipsilon/solidity/tree/eof-functions-rebased) which supports most of the EOF features. ## TLDR For Uniswap contracts we achieved benefits in all measured stats. - Deployed code and initcode size are `6.5%` smaller. - Gas usage for [deploy](https://github.com/ipsilon/solidity/blob/eof-functions-rebased/test/libsolidity/semanticTests/UniswapV3Flattened.sol#L5095) and [call step](https://github.com/ipsilon/solidity/blob/eof-functions-rebased/test/libsolidity/semanticTests/UniswapV3Flattened.sol#L5156) is ``~14%`` and ``~9%`` lower. - Gas usage for simple `swapExact0For1` is also `~5%` lower. - Execution time on `evmone` fast EVM implementation also looks better - For 100 calls of `swapExact0For1` (jump dest analysis enabled for legacy) execution time of EOF bytecode is `~15%` shorter than legacy. - Benchmarks prepared in a form of state tests ([legacy](https://github.com/ipsilon/evm-benchmarks/blob/eof-legacy-comp-bench/benchmarks/main/uniswapv3_many_swaps_legacy.json), [EOF](https://github.com/ipsilon/evm-benchmarks/blob/eof-legacy-comp-bench/benchmarks/main/uniswapv3_many_swaps_eof.json)) (1000 `swapExact0For1` calls) also shows measurable benefits from using EOF: - EOF: `35ms` (~10-15% faster than legacy w/o jump dest analysis) - Legacy: `39ms` - Legacy with jump dest analysis: `68ms` For `DNSRegistrar` contract test case we also achieved benefits in all metricses. - Deploy code and initcode size for [the test case](https://github.com/ipsilon/solidity/blob/ens-test/test/libsolidity/semanticTests/DNSRegistrarFlattened.sol) are accordingly`~6%` and `~1.5%` smaller. - Gas usage for `proveAndClaim` function call is `~10%` lower. - Also generated by `solc` compiler bytecode size of `DNSRegistrar` contract is `~10%` smaller. ## Uniswap-v3 Source: https://github.com/ipsilon/solidity/blob/eof-functions-rebased/test/libsolidity/semanticTests/UniswapV3Flattened.sol Command: **legacy** `ETH_EVMONE=<PATH_TO_EVMONE_BUILD>/libevmone.dylib ./build/test/./soltest -t "semanticTests/UniswapV3Flattened" -- --optimize --evm-version cancun --show-messages` **eof** `ETH_EVMONE=<PATH_TO_EVMONE_BUILD>/libevmone.dylib ./build/test/./soltest -t "semanticTests/UniswapV3Flattened" -- --optimize --evm-version cancun --eof-version 1 --show-messages` ### Code size **LEGACY:** init code: `31 202` bytes deployed code: `30 979` bytes **EOF:** init code: `29 236` bytes deployed code: `29 048` bytes ### Summary: init code: `~6.5%` less deployed code: `~6.5%`less ### Gas Usage Gas usage statistics for Uniswap V3 and simple run consists of: 1. deploy `UniswapV3Factory` 2. call `runTest` - deploy ERC20 tokens - deploy uniswap pool - add liquidity - simple swap **LEGACY:** deploy step: `6 832 734` total gas call step: `8 815 561` total **EOF:** deploy step: `5 925 377` total gas call step: `8 094 095` total ### Summary: deploy step: `~14%` less call step: `~9%` less ### Simple Swap `swapExact0For1` ``` Simple swap EOF: gas used: 77389 gas used (without refund): 80189 Simple swap legacy: gas used: 81329 gas used (without refund): 84129 ``` #### Execution time 100 calls of `swapExact0For1` Execution on evmone rev `d53b9e21cf39cec7f52253c141ea28572650a949` EOF: `13870 microseconds` legacy: `18539 microseconds` #### Benchmarks for 1000 calls of `swapExact0For1` as state tests Machine: ``` Apple M3 Pro 36GB RAM ``` evmone commands: `build/bin/./evmone-statetest --trace-summary ./test/evm-benchmarks/benchmarks/main/uniswapv3_many_swaps_legacy.json` `build/bin/./evmone-statetest --trace-summary ./test/evm-benchmarks/benchmarks/main/uniswapv3_many_swaps_eof.json` State test jsons: Legacy: https://gist.github.com/rodiazet/28a50d5e67d25e8dd9d87ad5962c9f25 EOF: https://gist.github.com/rodiazet/d9fbdb3f25ca77bb8ede133c1736e318 Summary: Tx Execution EOF: `35ms` Legacy: `39ms` Legacy with jump dest analysis: `68ms` #### Additional comment The code of this contract is bigger than UniswapV3Factory on mainnet because we added for test purpose `runTest` function which relies on ERC20 contract code and much more. But when running the test with empty `runTest` function with, EOF the bytecode is smaller by similar % than the one on mainnet. ## ENS DNSRegistrar Custom soltest: Source: https://github.com/ipsilon/solidity/tree/ens-test DNSRegistrar semantic test: https://github.com/ipsilon/solidity/blob/ens-test/test/libsolidity/semanticTests/DNSRegistrarFlattened.sol ### Code size **LEGACY:** init code: `27 845` bytes deployed code: `3 415` bytes **EOF:** init code: `26 171` bytes deployed code: `3 375` bytes #### Summary: init code: `~6%` less deployed code: `~1.5%`less ### Gas Usage Gas usage statistics for `DNSRegistrar::proveAndClaim` method call: **LEGACY:** call `proveAndClaim`: `251 846` total **EOF:** call `proveAndClaim`: `228 466` total #### Summary: call step: `~10%` less gas used for EOF #### Deployed code size comparison for clean [`DNSRegistrar` contract](https://github.com/ensdomains/ens-contracts/blob/staging/contracts/dnsregistrar/DNSRegistrar.sol) - legacy optimized: `7 058` bytes - eof optimized: `6 388` bytes Diff `~10%` **Compiler flags used:** legacy `--via-ir --bin-runtime --optimize` eof `--via-ir --bin-runtime --experimental-eof-version --optimize`